Hibernate OneToOne 延迟加载和级联
这就是我正在尝试做的事情。
- 创建与子级具有 OneToOne 关系的
- 父级 父级必须使用延迟加载来获取子级
- 如果父级被删除,子级也会被删除
- 如果子级被删除,父级不应受到影响
- 级联更新和删除必须进行转换进入 DDL
class Parent
@OneToOne(mappedBy = "parent", cascade = CascadeType.ALL)
public Child getChild()
class Child
@OneToOne(fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name="parent_id")
public Parent getParent()
我已经完全实现了第 1、3、4 点,第 5 点部分实现了正在工作,还需要解决如何翻译更新部分印度DDL。
第2点是这里的一个大问题,在我当前的解决方案中,父级不会延迟加载子级。然而,子级确实会延迟加载父级,但反转注释会扰乱级联(第 3、4 和 5 点)。
我现在很困惑,希望我错过了一些明显的事情,所以任何帮助将不胜感激。
编辑: Adeel Ansari
'fetch=FetchType.LAZY' 请求的代码已添加到 Parent 类中,其他与上面相同。
IParentDAO parentDAO = DAOFactory.getFactory().getParentDAO();
parentDAO.beginTransaction();
//findByPrimaryKey uses 'org.hibernate.Session.get(Class clazz, Serializable id)'
parentDAO.findByPrimaryKey(1l);
parentDAO.commitTransaction();
生成的 hibernate 查询,一个获取 Parent,一个获取 Child:
Hibernate: select parent0_.id as id0_0_ from parents parent0_ where parent0_.id=?
Hibernate: select child0_.id as id1_0_, child0_.parent_id as parent2_1_0_ from childs child0_ where child0_.parent_id=?
这是 findByPrimaryKey 的代码:
public class HibernateParentDAO extends HibernateDAO<Parent, Long> implements IParentDAO {
public HibernateParentDAO() {
super(Parent.class);
}
}
public abstract class HibernateDAO<T, ID extends Serializable> implements IGenericDAO<T, ID> {
private Class<T> persistentClass;
public HibernateDAO(Class<T> c) {
persistentClass = c;
}
@SuppressWarnings("unchecked")
public T findByPrimaryKey(ID id) {
return (T) HibernateUtil.getSession().get(persistentClass, id);
}
}
Here's what I'm trying to do.
- Create a parent with a OneToOne relation to a child
- The parent has to fetch the children using lazy loading
- If parent is removed, so is the child
- If the child is removed, the parent should not be affected
- The cascade update and delete has to be translated into DDL
class Parent
@OneToOne(mappedBy = "parent", cascade = CascadeType.ALL)
public Child getChild()
class Child
@OneToOne(fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name="parent_id")
public Parent getParent()
I've got point 1, 3, 4 fully working and Point 5 partially working, still need to solve how to translate the update part indo DDL.
Point 2 is the big issue here, with my current solution the parent does not load the child lazily. The child however does load the parent lazily, but inverting the annotations would mess upp the cascading (points 3, 4 and 5).
I'm very confused right now, hoping I've missed something obvious, so any help would be greatly appreciated.
EDIT: Code requested by Adeel Ansari
'fetch=FetchType.LAZY' has been added to class Parent, otherwise the same as above.
IParentDAO parentDAO = DAOFactory.getFactory().getParentDAO();
parentDAO.beginTransaction();
//findByPrimaryKey uses 'org.hibernate.Session.get(Class clazz, Serializable id)'
parentDAO.findByPrimaryKey(1l);
parentDAO.commitTransaction();
The resulting hibernate queries, one fetching Parent and one fetching Child:
Hibernate: select parent0_.id as id0_0_ from parents parent0_ where parent0_.id=?
Hibernate: select child0_.id as id1_0_, child0_.parent_id as parent2_1_0_ from childs child0_ where child0_.parent_id=?
Here's the code for findByPrimaryKey:
public class HibernateParentDAO extends HibernateDAO<Parent, Long> implements IParentDAO {
public HibernateParentDAO() {
super(Parent.class);
}
}
public abstract class HibernateDAO<T, ID extends Serializable> implements IGenericDAO<T, ID> {
private Class<T> persistentClass;
public HibernateDAO(Class<T> c) {
persistentClass = c;
}
@SuppressWarnings("unchecked")
public T findByPrimaryKey(ID id) {
return (T) HibernateUtil.getSession().get(persistentClass, id);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我也遇到过类似的问题。有几种不同的解决方案,但它们都是解决方法。
简短的回答是:Hibernate 不支持惰性一对一关系。
长答案(解决方法)是:
将关系声明为一对一的关系(子级)和一对多的关系(父级)。因此,
parent.getchild()
返回一个集合,但它将能够使用延迟加载。您可以尝试让父级和子级共享主键,但这需要您更改架构。
您可以尝试在数据库中配置一个视图来反映这种一对一关系。
I've been having a similar issue. There are a few different solutions, but all of them are workarounds.
The short answer is: Hibernate does NOT support lazy one-to-one relationships.
The long answer (workaround) is:
Declare the relationship to be one-to-one on one side (child), and one-to-many on the other side (parent). Thus a
parent.getchild()
returns a set, yet it will be able to use lazy loading.You can try to have the parent and the children to share the primary key, but this would require you to alter the schema.
You can try to configure a view in your database reflecting this one-to-one relationship.
[这部分不再成立]
在您的
Parent
中修改此内容,如下所示,应该可以工作。
[编辑解释为什么它不起作用]
参考:http://community.jboss.org/wiki/Someexplanationsonlazyloadingone-to-one< /a>
[编辑以包含解决方法]
您可以使用
optional=false
和@LazyToOne
用于非可选关系。不要忘记包含cascade={CascadeType.PERSIST,CascadeType.REMOVE}
。因为,对于非可选关系来说,这是显而易见的。下面是一个示例,这应该适合您,因为我可以看到您正在使用
cascade=CascadeType.ALL
,这意味着不可选。不是吗?但对于可选关系,您可能需要考虑iliaden,此处给出的解决方法。[This part doesn't hold anymore]
Modify this in your
Parent
like below,Should work.
[Edited to explain why it will not work]
Reference: http://community.jboss.org/wiki/Someexplanationsonlazyloadingone-to-one
[Edited to include a workaround]
You can use
optional=false
and@LazyToOne
for the relationship that is not optional. Don't forget to includecascade={CascadeType.PERSIST,CascadeType.REMOVE}
. Since, it is obvious for a not-optional relationship. Below is an example,This should work for you, as I can see you are using
cascade=CascadeType.ALL
, which means not-optional. Isn't it? But for optional relationship, you might like to consider workaround given by iliaden, here.您是否尝试过@OneToOne(fetch = FetchType.LAZY,可选= false)?
另请查看此博客和此主题。
Have you tried
@OneToOne(fetch = FetchType.LAZY, optional=false)
?Also check this blog and this thread.
@一对一关系不支持延迟初始化。
要获取对象,您不要将 FetchType.LAZY 放入子类中并获取所有子对象。
@One-to-one relationship not support lazy initialization.
To get object you don't put FetchType.LAZY in child class and obtain all child object.