Entitymanager Unable to remove entity problem

Source: Internet
Author: User

Today encountered a strange thing, using the Entitymanager.remove (entity) method to delete an entity, deleted, and do not error. Later through the multi-checks to solve the problem.


ERD

650) this.width=650; "src=" Http://s3.51cto.com/wyfs02/M00/7F/49/wKioL1cY4PXDaMjhAAA3p6ZllUk448.png "title=" Image 1.png "alt=" Wkiol1cy4pxdamjhaaa3p6zlluk448.png "/>


Entity definition

-------------  First entity a ---------------@Entitypublic  class A {      @Id     private Long id;          @Column (nullable = false, unique = true, length = 60)      private string internalkey;        @ Onetomany (mappedby =  "B", cascade = cascadetype.all, orphanremoval =  true)     private List<B> bs = new ArrayList<> (); &NBSP;&NBSP;&NBSP;&NBSP, ...} -------------  A second entity b ---------------@Entitypublic  class B {      @Id     private Long id;          @ManyToOne      @JoinColumn (name =  "A_internalkey",  referencedcolumnname = " Internalkey ")     private a a;   &nbsp ...}


Data

Table a:id internalkey---------------------1 a1table b:id a_internalkey---------------------1 A12 A1


Problem

It is possible to delete record B (id:2) directly from table B based on years of experience in manipulating data with SQL scripts. There is no foreign key reference to table B on table A, so you can delete the data on table B directly, and the database management system will not be unhappy. However, when you use the Entitymanager Remove (entity) method in JPA to delete B (id:2), the problem occurs. Remove does not delete the B (id:2) record, not to mention the database records, even the SQL statements are not sent from the JEE container. And, even more deadly, no! Yes! Reported Wrong!

I made a replacement scheme and deleted B (id:2) directly with the JPQL statement, and the result was successful. Hehe, this is not the end, or I do not have to take the trouble to record this thing. After I removed B (id:2), I tried to save the changes to a, and then there was a problem. JPA Error, said B (id:2) can not find, I faint. What is the situation, B (Id:2) has been deleted by me, how to persist a when the JPA is to check a deleted object? I'm sure after I delete B (id:2) with JPQL, I manually removed B (id:2) from the A.bs collection, why is this B (id:2) haunting?


Analysis

After flipping through some of the documents, I was vaguely aware that the problem should be related to several states of the entity (especially the detached state) and the cache in the O/R mapping framework. To be blunt, that is where the program produces inconsistent data. In general, the resulting inconsistency may be related to the state, life cycle, or scope of access of the managed object. Then, in the case of JPA, the corresponding entity's lifecycle or access mechanism (caching mechanism) should be considered.

Continue to delve into the discovery that this issue is due to a combination of various aspects of the production.

First, the key point of the problem: A and B bidirectional onetomany (bidirectional one-to-many relationship).

This is a good understanding, just like the garbage collection mechanism in Java, the object being used is not GC. Similarly, the quoted child, which is this B (Id:2), has been quoted by a (id:1), how did JPA let you kill him?! Previously not mentioned, A (id:1) was read by JPA before removing B (id:2). A (id:1) should still be in the JPA cache when I try to delete B (id:2). according to the annotation annotation on the entity, A (id:1) should have both B (id:1), B (Id:2) references (that is, the two elements in the list<b> BS collection). The removal of JPA is for some protection and will not allow you to delete the quoted B (Id:2).

Of course, if you insist on deleting, you can use Entitymanager.createquery ("Delete from B WHERE b.id=2"). Executeupdate (); To forcibly delete the specified database record. Because CreateQuery (). Executeupdate () sends the specified SQL to the DBMS, and if there is an error, the exception is presented to the JPA framework by the DBMS through the underlying JDBC and eventually through Entitymanager. I just used this method to force B (id:2) to get rid of.

The next thing to say is factor two: the cache is inconsistent with the actual database

Look at the contents of the red section above. Did you think of anything? Before removing B (id:2), A (id:1) with references to B (id:1) and B (Id:2) remain in the cache. When B (Id:2) is forcibly removed by me with JPQL, there is no code to update a (ID:1) in the cache, so a (id:1) should have a reference to B (Id:2). Next, you want to persist a (id:1) change. Although I later manually made A.bs.remove (b (Id:2)) (the reference to B (Id:2) was removed from the BS collection), it is regrettable that a (id:1) is already in the detached state (i.e., the Free State, leaving a (id:1) that is already in a free State called a (ID : 1)). Changes to an object that is already in a free State are not mapped to the corresponding entity, in other words, a (id:1) in the JPA cache will not be updated, no matter what I do with a (id:1). And, when I tried to persist a free object A (id:1), JPA passed a (id:1). Equals (A (id:1)) comparison, that a (id:1) = = A (id:1), because the ID of two objects is the same, Hashcode, so JPA finds a (id:1) from the cache, tries to persist again, and the next thing doesn't need me to say, JPA error, and tip I can't find B (id:2). What Why are you looking for B (id:2)? Oh, that's because the cascade definition on a,)


Solution Solutions

I have two solutions here:

1, to update A as the starting point, after rejecting B (id:2), persist a. Due to the Cascade set on a, the JPA cascade deletes B (id:2) while updating a

2, you can forcibly delete B (Id:2), but before any action on a (id:1), go fecth A (id:1), that is, forcibly refresh the JPA cache.


I personally recommend the first option.


This article is from the "Bitterjava" blog, make sure to keep this source http://rickqin.blog.51cto.com/1096449/1766492

Entitymanager Unable to remove entity problem

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.