Wednesday, February 8, 2017

JPA Persist vs Merge

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