Hibernation merge loses data

I get a weird issue with Hibernate and merge.

The structure of the classes in question is as follows:

Project --> CaseWorkerA --|> CaseWorker --|> User 

So basically I have a Project class that contains a reference to CaseWorkerA, which is a subclass of CaseWorker, which is again a subclass of User.

In code:

 public class Project { [...] private CaseWorkerA caseWorkerA; @ManyToOne(fetch = FetchType.EAGER) @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.REFRESH, org.hibernate.annotations.CascadeType.MERGE }) @JoinColumn(name = "CaseWorker_A") public CaseWorkerA getCaseWorkerA() { return caseWorkerA; } } 

Then we have a user hierarchy:

 public class User { [...] } public class CaseWorker extends User { private CaseWorkerStatus status; @Enumerated(EnumType.STRING) public CaseWorkerStatus getStatus() { return status; } [...] } public class CaseWorkerA extends CaseWorker { [...] } 

Then in the Dao class there is a method for storing the project:

 public class ProjectDao { [...] public Project saveUpdateProject(final Project project) { if (project.getId() == null) { getSession(false).save(project); } else { project = (Project) getSession(false).merge(project); } getHibernateTemplate().flush(); return project; } } 

Now the problem is as follows:

The Tao method gets the project that exists in the database. This project is associated with CaseWorkerA, which has the status CaseWorkerStatus.ACTIVE (both in the database and in the internal object). But after the merger, the status of a social worker becomes zero.

I really don’t understand how this is possible, since the value in the database is the same as in the stored object, I would expect it to remain unchanged after the merge.

(There are no triggers in the database in this field.)

(I will try to change the dao method to use saveOrUpdate instead, but even if this fixes the problem, I still really would like to know what caused it in the first place).

Update:

So, I was busy with the debugger and found the following: When I requested a session for the CaseWorker in question, it appeared with its set of status fields (in fact, the returned object was exactly the one that was associated with the Project).

Running saveOrUpdate and then retrieving led to the creation of CaseWorker with the status field set. So this is a problem with the merge method.

+7
source share
1 answer

To understand this, it turned out that there was a second path from Project to User (lastChangedBy), where someone decided to cascade for some strange reason. Therefore, when the person who last changed the project was CaseWorker, then lastChangedBy referred to him as a user who does not know anything about the status, so he was saved by zero.

the code:

 public class Project { private User changedBy; @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.REFRESH, org.hibernate.annotations.CascadeType.MERGE }) @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "changed_by") public User getChangedBy() { return this.changedBy; } [...] } 

The user that was set as changedBy was retrieved from the database as follows:

 public class UserDao { public User getUser(final String userName) { return (User) getSession(false).createQuery("from User u where u.loginName = :username").setParameter("username", userName).uniqueResult(); } } 

Sincerely, even if the user you are finishing receiving is CaseWorker, fields related to CaseWorker are not received.

In any case, deleted the unecceary cascade, and all this is good :)

0
source

All Articles