Tob*_*obb 7 java inheritance hibernate hibernate-cascade
我遇到了Hibernate和合并的奇怪问题.
有问题的类的结构如下:
Project --> CaseWorkerA --|> CaseWorker --|> User
Run Code Online (Sandbox Code Playgroud)
所以基本上我有一个Project类,它包含对CaseWorkerA的引用,CaseWorkerA是CaseWorker的子类,它也是User的子类.
在代码中:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们有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 {
[...]
}
Run Code Online (Sandbox Code Playgroud)
然后,在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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,问题如下:
Dao方法接收数据库中存在的项目.此项目连接到CaseWorkerA,其状态为CaseWorkerStatus.ACTIVE(在数据库和incomming对象中).但在合并之后,案件工作者的状态变为空.
我真的不明白这是怎么可能的,因为数据库中的值是相同的,就像要存储的对象一样,我希望它在合并后保持不变.
(此字段的数据库中没有触发器..)
(我将尝试更改dao-method以使用saveOrUpdate,但即使这将解决问题,我仍然非常想知道是什么原因造成的).
更新:
所以我摆弄了调试器,发现了以下内容:当我查询有问题的CaseWorker的会话时,它出现了它的状态字段集(实际上,返回的对象正是连接到Project的对象).
执行saveOrUpdate,然后执行get,导致CaseWorker设置了status-field.所以它似乎是合并方法的一个问题..
设法弄清楚,结果发现从项目到用户还有第二条路径(lastChangedBy之类的东西),有人出于某种奇怪的原因决定放置级联。因此,当最后更改项目的人是 CaseWorker 时,lastChangedBy 将其引用为 User,而 User 不知道任何有关状态的信息,因此它存储为 null。
代码:
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;
}
[...]
}
Run Code Online (Sandbox Code Playgroud)
从数据库中检索设置为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();
}
}
Run Code Online (Sandbox Code Playgroud)
显然,即使最终检索的用户是 CaseWorker,也不会检索与 CaseWorker 相关的字段。
无论如何,删除了不必要的级联,一切都很好:)