[英]Hibernate merge loses data
I am getting a strange problem with Hibernate and merge. 我遇到了Hibernate和合并的奇怪问题。
The structure of the classes in question is like this: 有问题的类的结构如下:
Project --> CaseWorkerA --|> CaseWorker --|> User
So basically I have a Project class, which contains a reference to a CaseWorkerA, which is a subclass of CaseWorker, which again is a subclass of User. 所以基本上我有一个Project类,它包含对CaseWorkerA的引用,CaseWorkerA是CaseWorker的子类,它也是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 the User-hierarchy: 然后我们有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, there is a method in a Dao-class, for storing a project: 然后,在Dao类中有一个方法用于存储项目:
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 Dao-method recieves a project that exists in the database. Dao方法接收数据库中存在的项目。 This project is connected to a CaseWorkerA, which has a status CaseWorkerStatus.ACTIVE (in both the database and in the incomming object).
此项目连接到CaseWorkerA,其状态为CaseWorkerStatus.ACTIVE(在数据库和incomming对象中)。 But after the merge, the status of the caseworker becomes null.
但在合并之后,案件工作者的状态变为空。
I really don't get how this is possible, since the value is the same in the database, as in the object to be stored, I would expect it to stay the same after the merge. 我真的不明白这是怎么可能的,因为数据库中的值是相同的,就像要存储的对象一样,我希望它在合并后保持不变。
(There are no triggers in the database for this field..) (此字段的数据库中没有触发器..)
(I am going to try to change the dao-method to use saveOrUpdate instead, but even if this will fix the problem I would still very much like to know what caused it in the first place). (我将尝试更改dao-method以使用saveOrUpdate,但即使这将解决问题,我仍然非常想知道是什么原因造成的)。
Update: 更新:
So I fiddled around with the debugger, and found the following: When I queried the session for the CaseWorker in question, it appeared with it's status-field set (actually, the object returned was exactly the one that was connected to the Project). 所以我摆弄了调试器,发现了以下内容:当我查询有问题的CaseWorker的会话时,它出现了它的状态字段集(实际上,返回的对象恰好是连接到Project的对象)。
Doing a saveOrUpdate, and then a get, resulted in a CaseWorker with the status-field set. 执行saveOrUpdate,然后执行get,导致CaseWorker设置了status-field。 So it seems to be a problem with the merge method..
所以它似乎是合并方法的一个问题..
Managed to figure it out, it turned out that there was a second path from Project to User (lastChangedBy kind of thing), where someone had decided to put cascade for some strange reason. 管理好弄明白,事实证明,从项目到用户有一条第二条路径(lastChangedBy类似的东西),有人因某种奇怪的原因决定放入级联。 So when the person who last changed the project was a CaseWorker, then the lastChangedBy referenced it as a User, which doesn't know anything about the status, so it was stored a null.
因此,当最后一次更改项目的人是CaseWorker时,lastChangedBy将其引用为User,它不了解状态,因此存储为null。
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 like this: 设置为changedBy的用户从数据库中检索如下:
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();
}
}
Appearantly, even if the user one ends up retrieving is-a CaseWorker, the fields pertaining to a CaseWorker does not get retrieved.. 显然,即使最终检索的用户是一个CaseWorker,也不会检索与CaseWorker相关的字段。
Anyways, removed the uneccesary cascade, and it's all good :) 无论如何,删除了不成功的级联,这一切都很好:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.