JPA2.0: delete an object in OneToMany RelationShip

How to delete an object in a OneToMany relationship.

@Entity @NamedQueries({ @NamedQuery(name="User.findByUserNamePassword", query="select c from User c where c.userName = :userName AND c.password = :password") }) @Table(name="\"USER\"") public class User implements Serializable { @OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemove=true) private List<Profession> professions; public List<Profession> getProfessions() { return professions; } public void setProfessions(List<Profession> professions) { this.professions = professions; } public void addProfession(Profession profession){ if(this.professions == null){ this.professions = new ArrayList<Profession>(); } this.professions.add(profession); profession.setUser(this); } public void removeProfession(Profession profession){ if(this.professions != null){ professions.remove(profession); profession.setUser(null); } } } 

Domestic profession

 @Entity public class Profession implements Serializable { @ManyToOne @JoinColumn(name="UserId", nullable=false) private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } 

Then inside my EJB I have this

 @Stateless @LocalBean @TransactionAttribute(TransactionAttributeType.REQUIRED) public class ScholarEJB{ /** * Add a profession to a target user * @param user * @param profession */ public void addProfession(User user, Profession profession){ //Put the user in a managed state. It is important to do this before //adding a new profession onto user user = find(User.class, user.getId()); user.addProfession(profession); this.create(user); //This is persist action } public void removeProfession(User user, Profession profession){ //Put the user in a managed state. It is important to do this before //adding a new profession onto user user = find(User.class, user.getId()); user.remove(user); this.update(user); //merge action //this.create(user) //also try this as well, but it does not work } } 

Now addProfession works beautifully, but removeProfession does not work. Do not know why? Please help me. Do I need to evict caches?

+6
source share
5 answers

If professions are only part of this relationship, then you can guarantee that when the profession is removed from the user set, it will also be deleted from the database by including orphanRemoval on the OneToMany side of the relationship.

 @OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemoval=true) private List<Profession> professions; 

This JPA 2.0 specification contains

The JPA 2.0 specification states that

Associations that are listed as OneToOne or OneToMany support the use of the orphanRemoval option. The following actions apply when orphanRemoval:

If the object that is the object of the relationship is removed from the relationship (by setting the relation to null or removing the subject from the collection relation), the delete operation will be applied to the object that is orphaned. The delete operation is applied during a flash operation. Orphaning functionality is intended for objects that are privately owned by the parent object. Portable applications otherwise should not depend on the specific order of removal, and do not reassign an entity that was orphaned to other relationships or otherwise try to save it. If the orphaned object is a separate, new, or deleted object, the semantics of orphanRemoval are not applied.

If the delete operation is applied to a managed source object, the delete operation will be cascaded to the target in accordance with the rules of section 3.2.3 (and therefore, there is no need to specify cascade = REMOVE for the relationship) [20].

+9
source

My guess about what is going on is that your user has OneToMany related to the profession, and the user object has its own profession. When you delete a Profession, the user still has a link. Since the map is a cascade, it is saved. Profession.

You need to make sure that you delete the profession from user professions before deleting it.

If you use EclipseLink, there is a property that may also help, but the best solution is to fix the code to properly support your model. You can also delete the cascade.

"eclipselink.persistence-context.persist-on-commit" = "false"

or, "Eclipselink.persistence-context.commit-without persist-rules" = "true"

+4
source

You can try to clear the user's field from the profession:

 public void removeProfession(Profession profession){ if(this.professions != null){ professions.remove(profession); profession.setUser(null); // disassociate profession from user } } 

To be safe, I would also like to check that the current user who has passed the profession is equal to this , just in case someone goes into a profession belonging to another user.

+1
source

This is the solution to my initial question, however, I do not know if this is the best

My EJB bean

 @PersistenceContext(unitName="Bridgeye2-ejbPU") private EntityManager em; public <T> T create(T t) { em.persist(t); return t; } public <T> T find(Class<T> type, Object id) { return em.find(type, id); } public <T> void delete(T t) { t = em.merge(t); em.remove(t); } public <T> void removeAndClearCaches(T t){ this.delete(t); clearCaches(); } public <T> T update(T t) { return em.merge(t); 

Now in my controlled bean, I do it

 /** * Add a new profession */ public void addNewProfession(){ Profession profession = new Profession(); newProfessions.add(profession); } /** * Remove the profession * @param profession */ public void removeProfession(Profession profession){ //This will remove the `profession` of the list //at the presentation layer this.myProfessions.remove(profession); //This will remove the `profession` of the list //at the persistence layer scholarEJB.removeAndClearCaches(profession); } 
+1
source

I just added orphanRemoval = true with respect to OneToMany, and I solved it.

Class SolicitudRetorno :

 @OneToMany(mappedBy = "solicitud", cascade = CascadeType.ALL, orphanRemoval = true) @LazyCollection(LazyCollectionOption.FALSE) @NotAudited private List<RetornoMenor> hijosRetorno; 

RetornoMenor Class:

 @OneToMany(mappedBy = "solicitud", cascade = CascadeType.ALL, orphanRemoval = true) @LazyCollection(LazyCollectionOption.FALSE) @NotAudited private List<RetornoMenor> hijosRetorno; 
0
source

Source: https://habr.com/ru/post/885763/


All Articles