所以,我发现自己对Hibernate有很大的反响。当我开始开发我的Web应用程序时,我在所有地方使用“急切”加载,以便我可以轻松访问孩子,父母等。
过了一会儿,我遇到了第一个问题 - 重新保存已删除的对象。多个stackoverflow线程建议我应该从它所在的所有集合中删除该对象。阅读这些建议使我的“蜘蛛感觉”发痒,因为我的关系不是很简单,我不得不迭代多个对象,这使得我的代码看起来很像丑陋,让我想知道这是不是最好的方法。
例如,删除Employee时(在某种意义上,User可以作为多个不同的Employe)属于User。假设员工可以将反馈留给Party,因此Employee可以有多个反馈,Party可以有多个反馈。此外,Employee和Party都属于某种父对象,比如说一个组织。基本上,我们有:
class User {
// Has many
Set<Employee> employees;
// Has many
Set<Organization> organizations;
// Has many through employees
Set<Organization> associatedOrganizations;
}
class Employee {
// Belongs to
User user;
// Belongs to
Organization organization;
// Has many
Set<Feedback> feedbacks;
}
class Organization {
// Belongs to
User user;
// Has many
Set<Employee> employees;
// Has many
Set<Party> parties;
}
class Party {
// Belongs to
Organization organization;
// Has many
Set<Feedback> feedbacks;
}
class Feedback {
// Belongs to
Party party;
// Belongs to
Employee employee;
}
这是我在删除员工时最终得到的结果:
// First remove feedbacks related to employee
Iterator<Feedback> iter = employee.getFeedbacks().iterator();
while (iter.hasNext()) {
Feedback feedback = iter.next();
iter.remove();
feedback.getParty().getFeedbacks().remove(feedback);
session.delete(feedback);
}
session.update(employee);
// Now remove employee from organization
Organization organization = employee.getOrganization();
organization.getEmployees().remove(employee);
session.update(organization);
根据我的定义,这是丑陋的。我会假设使用
@Cascade({CascadeType.ALL})
然后Hibernate会通过简单地执行以下操作来神奇地从所有关联中删除Employee:
session.delete(employee);
相反,我得到:
Error during managed flush [deleted object would be re-saved by cascade (remove deleted object from associations)
所以,为了尝试让我的代码更清洁,甚至可能优化(有时懒惰的提取就足够了,有时候我需要急切),我试着懒得取几乎所有东西,并希望如果我这样做,例如:< / p>
employee.getFeedbacks()
然后很好地获取反馈,没有任何问题但是没有,一切都破裂了:
failed to lazily initialize a collection of role: ..., could not initialize proxy - no Session
我想到的下一件事就是删除对象插入/删除相关子对象的可能性,但这可能是一个糟糕的想法,在性能方面 - 单独插入每个对象
child.parent=parent
而不是批量
parent.children().add(children)
。
最后,我看到有多人建议创建我自己的自定义查询和东西,但在那时,为什么我甚至要打扰Hibernate?是不是真的没有办法解决我的问题比较干净,或者我错过了什么,还是我是白痴?
答案 0 :(得分:0)
如果我正确地理解了这个问题,那就是关于简单1:N
关系的层叠。在这种情况下,Hibernate可以很好地完成这项工作:
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(cascade = CascadeType.ALL,
mappedBy = "post", orphanRemoval = true)
private List<Comment> comments = new ArrayList<>();
}
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
private Post post;
}
代码:
Post post = newPost();
doInTransaction(session -> {
session.delete(post);
});
生成:
delete from Comment where id = 1
delete from Comment where id = 2
delete from Post where id = 1
但是如果你有其他(合成)集合,Hibernate没有机会知道哪些,所以你必须自己处理它们。
对于Hibernate和自定义查询,Hibernate提供的HQL比传统SQL更紧凑,但仍然不如注释透明。