这就是我想要做的事情。
班级家长
@OneToOne(mappedBy = "parent", cascade = CascadeType.ALL)
public Child getChild()
班级儿童
@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<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);
}
}
答案 0 :(得分:20)
我遇到过类似的问题。有几种不同的解决方案,但所有这些都是解决方法。
简短的回答是:Hibernate不支持懒惰的一对一关系。
长答案(解决方法)是:
声明关系在一边(孩子)是一对一,在另一边(父母)是一对多。因此,parent.getchild()
返回一个集合,但它将能够使用延迟加载。
您可以尝试让父级和子级共享主键,但这需要您更改架构。
您可以尝试在数据库中配置反映这种一对一关系的视图。
答案 1 :(得分:11)
[这部分不再存在]
在Parent
中修改此内容,如下所示
@OneToOne(mappedBy = "parent", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
public Child getChild()
应该工作。
[编辑解释为何不起作用]
加载B后,您可以打电话 getCee()获得C.但是看, getCee()是你的类和方法 Hibernate无法控制它。 Hibernate不知道什么时候有人 打算调用getCee()。这意味着 Hibernate必须放一个合适的 价值进入“cee”财产 它从数据库加载B。
如果为C,Hibernate启用了代理 可以放一个不是的C代理对象 已加载,但将在何时加载 有人用它。这给了懒惰 加载一对一。
但现在想象你的B对象可能或 可能没有相关的C. (约束= “假”)。什么应该 getCee()在特定B时返回 没有C?空值。但要记住, Hibernate必须设置正确的值 “cee”在它设定B的那一刻(因为 它不知道什么时候有人打电话 getCee())。代理在这里没有帮助 因为代理本身已经存在 非空对象。
如果你的B-> C映射是 强制(约束=真), Hibernate将使用C代理 导致延迟初始化。但 如果你允许B没有C,Hibernate 只是要检查C的存在 它加载的时刻B.但是一个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, here给出的解决方法。
答案 2 :(得分:7)
答案 3 :(得分:-1)
@一对一关系不支持延迟初始化。 要获取对象,您不要在子类中放置FetchType.LAZY 并获取所有子对象。
class Parent
@OneToOne(mappedBy = "parent", cascade = CascadeType.REMOVE)
public Child getChild()
class Child
@OneToOne(cascade = CascadeType.REMOVE)
public Parent getParent()