Hibernate OneToOne延迟加载和级联
这就是我想要做的。
- 创建一个与子项具有OneToOne关系的父项
- 父级必须使用延迟加载来获取子级
- 如果父母被移除,那么孩子也是如此
- 如果孩子被移除,父母不应受到影响
- 级联更新和删除必须转换为DDL
class级家长
@OneToOne(mappedBy = "parent", cascade = CascadeType.ALL) public Child getChild()
class级孩子
@OneToOne(fetch = FetchType.LAZY) @OnDelete(action = OnDeleteAction.CASCADE) @JoinColumn(name="parent_id") public Parent getParent()
我有点1,3,4完全工作, 第5点部分工作,仍然需要解决如何翻译更新部分indo 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 implements IParentDAO { public HibernateParentDAO() { super(Parent.class); } } public abstract class HibernateDAO implements IGenericDAO { private Class persistentClass; public HibernateDAO(Class c) { persistentClass = c; } @SuppressWarnings("unchecked") public T findByPrimaryKey(ID id) { return (T) HibernateUtil.getSession().get(persistentClass, id); } }
我一直有类似的问题。 有一些不同的解决方案,但所有这些都是解决方法。
简短的回答是:Hibernate不支持懒惰的一对一关系。
答案很长(解决方法)是:
-
将关系声明为一方(孩子)一对一,另一方(父母)一对多。 因此,
parent.getchild()
返回一个集合,但它将能够使用延迟加载。 -
您可以尝试让父级和子级共享主键,但这需要您更改架构。
-
您可以尝试在数据库中配置反映这种一对一关系的视图。
[此部分不再存在]
在您的Parent
修改,如下所示,
@OneToOne(mappedBy = "parent", cascade = CascadeType.ALL, fetch=FetchType.LAZY) public Child getChild()
应该管用。
[编辑解释为什么它不起作用]
在加载B之后,你可以调用getCee()来获得C.但是看看,getCee()是你的类的一个方法,而Hibernate无法控制它。 Hibernate不知道有人打算调用getCee()。 这意味着Hibernate必须在从数据库加载B时将适当的值放入“cee”属性。
如果为C启用了代理,Hibernate可以放置一个尚未加载的C代理对象,但会在有人使用它时加载。 这为一对一提供了延迟加载。
但现在想象你的B对象可能有也可能没有关联的C(约束=“假”)。 当特定B没有C时,getCee()应该返回什么? 空值。 但请记住,Hibernate必须在设置B时设置正确的“cee”值(因为它不知道有人会调用getCee())。 代理在这里没有帮助,因为代理本身已经是非null对象。
如果您的B-> C映射是强制性的(约束=真),Hibernate将使用C代理导致延迟初始化。 但是如果你允许B没有C,那么Hibernate只是在它加载B时检查C的存在。但是检查存在的SELECT效率很低,因为相同的SELECT可能不只是检查存在,而是加载整个对象。 懒惰的装载消失了。
参考: http : //community.jboss.org/wiki/Someexplanationsonlazyloadingone-to-one
[编辑包含一个变通方法]
您可以将optional=false
和@LazyToOne
用于非可选的关系。 不要忘记包含cascade={CascadeType.PERSIST,CascadeType.REMOVE}
。 因为,非选择性关系显而易见。 以下是一个例子,
@OneToOne(mappedBy="parent", optional=false, fetch=FetchType.LAZY, cascade={CascadeType.PERSIST,CascadeType.REMOVE}) @LazyToOne(LazyToOneOption.PROXY) public Child getChild(){...}
这应该适合你,因为我可以看到你使用cascade=CascadeType.ALL
,这意味着不可选。 不是吗? 但对于可选关系,您可能会考虑iliaden在此处给出的解决方法。
你试过@OneToOne(fetch = FetchType.LAZY, optional=false)
吗? 另请查看此博客和此主题。
@一对一的关系不支持延迟初始化 。 要获取对象, 不要将FetchType.LAZY放在子类中并获取所有子对象。
class Parent @OneToOne(mappedBy = "parent", cascade = CascadeType.REMOVE) public Child getChild() class Child @OneToOne(cascade = CascadeType.REMOVE) public Parent getParent()