Once again, Persist versus Merge
There are tons of posts on internet on this topic; I will not duplicate already existing info but just emphasize a simple sample showing that not understanding the basics of JPA notions can lead to very unpleasant side effects.
To began with some (very) simplified assertions on above mentioned operations:
- Persist will:
- turn your newly created entity into a managed one and will issue an INSERT statement at transaction commit or flush operation;
- For IDENTITY/SEQUENCE based PK generation the latest PK value is retrieved from the database and filled in the managed entity (which is the original one passed to the Persist operation!)
Merge will:
- Create a managed copy of your entity; this copy will be returned by the merge call while your original entity will not become managed(!)
- SELECT SQL statements will be issued in order to decide if and INSERT or UPDATE will be used prior the end of transaction/flush operation
- The appropriate SQL statement will be then issued (INSERT/UPDATE)
- For IDENTITY/SEQUENCE based PK generation the latest PK value is retrieved from the database and filled in the managed entity (not in the original one!)
Now, in conjunction with CascadeType.Persist/All applied on a @OneToMany relationship the disaster is eminent. Let me explain on a simple sample.
Suppose we have a Car entity (owned by a company) having as a property the current driver and we want to manage also the history of allocated drivers. We will be tempted to have something like this:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "carId")
private Collection<PersonHistory> personHistoryCollection;
Imagine the following scenario:
- We change the driver for a Car; the back end action automatically does the following operations:
- add a new driver to the
personHistoryCollection
- changes the previous current driver in
personHistoryCollection
last date he owned the car
- changes the current driver reference in the Car instance
- We call merge operation on the Car instance
At the moment of calling the merge we have the following situation:
- Car instance modified
- Previous
PersonHistory
( member in personHistoryCollection
) having last date modified
- A new
PersonHistory
entity added to the collection
The Persist operation will update in the database the Car
and, due to the CascadeType.All, will be subsequently applied also to all members of personHistoryCollection
updating the previous PersonHistory
entity and inserting a new PersonHistory
. The INSERT will not update the PK of the newly created PersonHistory
(the PK will remain NULL) due to the way Merge operation works on copies of original entity and thus leaving the collection in an inconsistent state.
Suppose you have chosen the @SessionScoped model for your backing bean and during the same Web session you add a new driver: the next merge operation sees that the previous PersonHistory
has a NULL PK and performs an INSERT instead on an UPDATE. Nice, isn’t it?
So, be sure you have a at least a basic understanding of persist/merge JPA operations and be cautious using CascadeTpe attributes. Apart from the inconsistencies between in session image and database image the merge operation applied in conjunction with CascadeType.* will lead to a lot of futile SQLECT statements.
PGgxIGlkPSJvbmNlYWdhaW5wZXJzaXN0dmVyc3VzbWVyZ2UiPk9uY2UgYWdhaW4sIFBlcnNp
c3QgdmVyc3VzIE1lcmdlPC9oMT4NCg0KPHA+VGhlcmUgYXJlIHRvbnMgb2YgcG9zdHMgb24g
aW50ZXJuZXQgb24gdGhpcyB0b3BpYzsgSSB3aWxsIG5vdCBkdXBsaWNhdGUgYWxyZWFkeSBl
eGlzdGluZyBpbmZvIGJ1dCBqdXN0IGVtcGhhc2l6ZSBhIHNpbXBsZSBzYW1wbGUgc2hvd2lu
ZyB0aGF0IG5vdCB1bmRlcnN0YW5kaW5nIHRoZSBiYXNpY3Mgb2YgSlBBIG5vdGlvbnMgY2Fu
IGxlYWQgdG8gdmVyeSB1bnBsZWFzYW50IHNpZGUgZWZmZWN0cy48L3A+DQoNCjxwPlRvIGJl
Z2FuIHdpdGggc29tZSAodmVyeSkgc2ltcGxpZmllZCBhc3NlcnRpb25zIG9uIGFib3ZlIG1l
bnRpb25lZCBvcGVyYXRpb25zOjwvcD4NCg0KPHVsPg0KPGxpPlBlcnNpc3Qgd2lsbDoNCg0K
PHVsPg0KPGxpPnR1cm4geW91ciBuZXdseSBjcmVhdGVkIGVudGl0eSBpbnRvIGEgbWFuYWdl
ZCBvbmUgYW5kIHdpbGwgaXNzdWUgYW4gSU5TRVJUIHN0YXRlbWVudCBhdCB0cmFuc2FjdGlv
biBjb21taXQgb3IgZmx1c2ggb3BlcmF0aW9uOzwvbGk+DQo8bGk+Rm9yIElERU5USVRZL1NF
UVVFTkNFIGJhc2VkIFBLIGdlbmVyYXRpb24gdGhlIGxhdGVzdCBQSyB2YWx1ZSBpcyByZXRy
aWV2ZWQgZnJvbSB0aGUgZGF0YWJhc2UgYW5kIGZpbGxlZCBpbiB0aGUgbWFuYWdlZCBlbnRp
dHkgKHdoaWNoIGlzIHRoZSBvcmlnaW5hbCBvbmUgcGFzc2VkIHRvIHRoZSBQZXJzaXN0IG9w
ZXJhdGlvbiEpPC9saT4NCjwvdWw+PC9saT4NCjxsaT48cD5NZXJnZSB3aWxsOjwvcD4NCg0K
PHVsPg0KPGxpPkNyZWF0ZSBhIG1hbmFnZWQgY29weSBvZiB5b3VyIGVudGl0eTsgdGhpcyBj
b3B5IHdpbGwgYmUgcmV0dXJuZWQgYnkgdGhlIG1lcmdlIGNhbGwgd2hpbGUgeW91ciBvcmln
aW5hbCBlbnRpdHkgd2lsbCBub3QgYmVjb21lIG1hbmFnZWQoISk8L2xpPg0KPGxpPlNFTEVD
VCBTUUwgc3RhdGVtZW50cyB3aWxsIGJlIGlzc3VlZCBpbiBvcmRlciB0byBkZWNpZGUgaWYg
YW5kIElOU0VSVCBvciBVUERBVEUgd2lsbCBiZSB1c2VkIHByaW9yIHRoZSBlbmQgb2YgdHJh
bnNhY3Rpb24vZmx1c2ggb3BlcmF0aW9uPC9saT4NCjxsaT5UaGUgYXBwcm9wcmlhdGUgU1FM
IHN0YXRlbWVudCB3aWxsIGJlIHRoZW4gaXNzdWVkIChJTlNFUlQvVVBEQVRFKTwvbGk+DQo8
bGk+Rm9yIElERU5USVRZL1NFUVVFTkNFIGJhc2VkIFBLIGdlbmVyYXRpb24gdGhlIGxhdGVz
dCBQSyB2YWx1ZSBpcyByZXRyaWV2ZWQgZnJvbSB0aGUgZGF0YWJhc2UgYW5kIGZpbGxlZCBp
biB0aGUgbWFuYWdlZCBlbnRpdHkgKG5vdCBpbiB0aGUgb3JpZ2luYWwgb25lISk8L2xpPg0K
PC91bD48L2xpPg0KPC91bD4NCg0KPHA+Tm93LCBpbiBjb25qdW5jdGlvbiB3aXRoIENhc2Nh
ZGVUeXBlLlBlcnNpc3QvQWxsIGFwcGxpZWQgb24gYSBAT25lVG9NYW55IHJlbGF0aW9uc2hp
cCB0aGUgZGlzYXN0ZXIgaXMgZW1pbmVudC4gTGV0IG1lIGV4cGxhaW4gb24gYSBzaW1wbGUg
c2FtcGxlLjwvcD4NCg0KPHA+U3VwcG9zZSB3ZSBoYXZlIGEgQ2FyIGVudGl0eSAob3duZWQg
YnkgYSBjb21wYW55KSBoYXZpbmcgYXMgYSBwcm9wZXJ0eSB0aGUgY3VycmVudCBkcml2ZXIg
YW5kIHdlIHdhbnQgdG8gbWFuYWdlIGFsc28gdGhlIGhpc3Rvcnkgb2YgYWxsb2NhdGVkIGRy
aXZlcnMuIFdlIHdpbGwgYmUgdGVtcHRlZCB0byBoYXZlIHNvbWV0aGluZyBsaWtlIHRoaXM6
PC9wPg0KDQo8cHJlPjxjb2RlIGNsYXNzPSJqYXZhIj4gICAgQE9uZVRvTWFueShjYXNjYWRl
ID0gQ2FzY2FkZVR5cGUuQUxMLCBtYXBwZWRCeSA9ICZxdW90O2NhcklkJnF1b3Q7KQ0KICAg
IHByaXZhdGUgQ29sbGVjdGlvbiZsdDtQZXJzb25IaXN0b3J5Jmd0OyBwZXJzb25IaXN0b3J5
Q29sbGVjdGlvbjsNCjwvY29kZT48L3ByZT4NCg0KPHA+SW1hZ2luZSB0aGUgZm9sbG93aW5n
IHNjZW5hcmlvOjwvcD4NCg0KPHVsPg0KPGxpPldlIGNoYW5nZSB0aGUgZHJpdmVyIGZvciBh
IENhcjsgdGhlIGJhY2sgZW5kIGFjdGlvbiBhdXRvbWF0aWNhbGx5IGRvZXMgdGhlIGZvbGxv
d2luZyBvcGVyYXRpb25zOg0KDQo8dWw+DQo8bGk+YWRkIGEgbmV3IGRyaXZlciB0byB0aGUg
PGNvZGU+cGVyc29uSGlzdG9yeUNvbGxlY3Rpb248L2NvZGU+PC9saT4NCjxsaT5jaGFuZ2Vz
IHRoZSBwcmV2aW91cyBjdXJyZW50IGRyaXZlciBpbiA8Y29kZT5wZXJzb25IaXN0b3J5Q29s
bGVjdGlvbjwvY29kZT4gbGFzdCBkYXRlIGhlIG93bmVkIHRoZSBjYXI8L2xpPg0KPGxpPmNo
YW5nZXMgdGhlIGN1cnJlbnQgZHJpdmVyIHJlZmVyZW5jZSBpbiB0aGUgQ2FyIGluc3RhbmNl
PC9saT4NCjwvdWw+PC9saT4NCjxsaT5XZSBjYWxsIG1lcmdlIG9wZXJhdGlvbiBvbiB0aGUg
Q2FyIGluc3RhbmNlPC9saT4NCjwvdWw+DQoNCjxwPkF0IHRoZSBtb21lbnQgb2YgY2FsbGlu
ZyB0aGUgbWVyZ2Ugd2UgaGF2ZSB0aGUgZm9sbG93aW5nIHNpdHVhdGlvbjo8L3A+DQoNCjx1
bD4NCjxsaT5DYXIgaW5zdGFuY2UgbW9kaWZpZWQ8L2xpPg0KPGxpPlByZXZpb3VzIDxjb2Rl
PlBlcnNvbkhpc3Rvcnk8L2NvZGU+ICggbWVtYmVyIGluIDxjb2RlPnBlcnNvbkhpc3RvcnlD
b2xsZWN0aW9uPC9jb2RlPikgaGF2aW5nIGxhc3QgZGF0ZSBtb2RpZmllZDwvbGk+DQo8bGk+
QSBuZXcgPGNvZGU+UGVyc29uSGlzdG9yeTwvY29kZT4gZW50aXR5IGFkZGVkIHRvIHRoZSBj
b2xsZWN0aW9uPC9saT4NCjwvdWw+DQoNCjxwPlRoZSBQZXJzaXN0IG9wZXJhdGlvbiB3aWxs
IHVwZGF0ZSBpbiB0aGUgZGF0YWJhc2UgdGhlIDxjb2RlPkNhcjwvY29kZT4gYW5kLCBkdWUg
dG8gdGhlIENhc2NhZGVUeXBlLkFsbCwgd2lsbCBiZSBzdWJzZXF1ZW50bHkgYXBwbGllZCBh
bHNvIHRvIGFsbCBtZW1iZXJzIG9mIDxjb2RlPnBlcnNvbkhpc3RvcnlDb2xsZWN0aW9uPC9j
b2RlPiB1cGRhdGluZyB0aGUgcHJldmlvdXMgPGNvZGU+UGVyc29uSGlzdG9yeTwvY29kZT4g
ZW50aXR5IGFuZCBpbnNlcnRpbmcgYSBuZXcgPGNvZGU+UGVyc29uSGlzdG9yeTwvY29kZT4u
IFRoZSBJTlNFUlQgd2lsbCBub3QgdXBkYXRlIHRoZSBQSyBvZiB0aGUgbmV3bHkgY3JlYXRl
ZCA8Y29kZT5QZXJzb25IaXN0b3J5PC9jb2RlPiAodGhlIFBLIHdpbGwgcmVtYWluIE5VTEwp
IGR1ZSB0byB0aGUgd2F5IE1lcmdlIG9wZXJhdGlvbiB3b3JrcyBvbiBjb3BpZXMgb2Ygb3Jp
Z2luYWwgZW50aXR5IGFuZCB0aHVzIGxlYXZpbmcgdGhlIGNvbGxlY3Rpb24gaW4gYW4gaW5j
b25zaXN0ZW50IHN0YXRlLjwvcD4NCg0KPHA+U3VwcG9zZSB5b3UgaGF2ZSBjaG9zZW4gdGhl
IEBTZXNzaW9uU2NvcGVkIG1vZGVsIGZvciB5b3VyIGJhY2tpbmcgYmVhbiBhbmQgZHVyaW5n
IHRoZSBzYW1lIFdlYiBzZXNzaW9uIHlvdSBhZGQgYSBuZXcgZHJpdmVyOiB0aGUgbmV4dCBt
ZXJnZSBvcGVyYXRpb24gc2VlcyB0aGF0IHRoZSBwcmV2aW91cyA8Y29kZT5QZXJzb25IaXN0
b3J5PC9jb2RlPiBoYXMgYSBOVUxMIFBLIGFuZCBwZXJmb3JtcyBhbiBJTlNFUlQgaW5zdGVh
ZCBvbiBhbiBVUERBVEUuIE5pY2UsIGlzbiYjODIxNzt0IGl0PzwvcD4NCg0KPHA+U28sIGJl
IHN1cmUgeW91IGhhdmUgYSBhdCBsZWFzdCBhIGJhc2ljIHVuZGVyc3RhbmRpbmcgb2YgcGVy
c2lzdC9tZXJnZSBKUEEgb3BlcmF0aW9ucyBhbmQgYmUgY2F1dGlvdXMgdXNpbmcgQ2FzY2Fk
ZVRwZSBhdHRyaWJ1dGVzLiBBcGFydCBmcm9tIHRoZSBpbmNvbnNpc3RlbmNpZXMgYmV0d2Vl
biBpbiBzZXNzaW9uIGltYWdlIGFuZCBkYXRhYmFzZSBpbWFnZSB0aGUgbWVyZ2Ugb3BlcmF0
aW9uIGFwcGxpZWQgaW4gY29uanVuY3Rpb24gd2l0aCBDYXNjYWRlVHlwZS4qIHdpbGwgbGVh
ZCB0byBhIGxvdCBvZiBmdXRpbGUgU1FMRUNUIHN0YXRlbWVudHMuPC9wPg0K
No comments :
Post a Comment