我们有以下关系:
汽车归个人所有。
一个人可以拥有很多辆车。
这是汽车的映射:
<hibernate-mapping package="fr.recouv.scribe.core.bo">
<class name="Car" table="car">
<id name="id" column="id_car" unsaved-value="0">
<generator class="sequence">
<param name="sequence">car_id_car_seq</param>
</generator>
</id>
<many-to-one name="person" update="false" column="id_person" class="Person" />
<property
</class>
我有一个带有此签名的网络服务:
public void insert(Car car, int idPersonOwner)
我想根据特定人的 ID 插入一辆车。 现在我的代码如下所示:
Car car = new Car();
Person owner = personDao.get(idPersonOwner);
car.setPerson(owner);
carDao.save(car);
personDao.get(idPersonOwner) 的 hibernate 实现看起来像
public Person get(in idPerson){
return session.get(Person.class, id);
}
此方法的缺点:
- 即使我只需要从 SQL View 中获取他的 ID,所有 Person 对象都会加载
- 如果人员映射发生变化(例如延迟加载设置为 false 等),该操作可能会生成超过 2 个查询
我的实际解决方法: 就是直接将外键映射为整数
<property column="id_person" name="idPerson" />
这个解决方案不是面向对象的,而且不太美观。 如果明天我需要检索汽车的所有者,我必须像以前一样重新映射 person 对象并 update=false
是否可以仅加载给定的人员的代理他的 ID,这将导致查询 验证此人是否存在及其主键,并可选择以惰性模式加载其他字段(如果调用)。
我尝试过 session.load 但这不是解决方案。该对象永远不会为空(没有查询测试他的存在)或者不会抛出异常,直到您访问其他字段 从数据库中实际加载对象。
最佳答案
是的,这正是session.load
( EntityManager.getReference
如果使用 JPA)用于。假设实体存在,它会加载对象的代理。
当然,如果在提交时外键约束因该人实际上不存在而中断,则可能会出现异常。但是,如果其他事务在提交之前删除了该人,您也可以使用 Session.get
来获取它。
如果您确实想检查此人是否存在,请执行仅返回 bool 值(或计数)的专用查询,并在您知道此人存在时使用 Session.load
:
Number count =
session.createQuery("select count(p.id) from Person p where p.id = :theId")
.setLong("theId", theId)
.uniqueResult();
if (count.intValue() > 0) {
Person p = session.load(Person.class, theId);
}
else {
// throw exception
}
关于仅使用主键的 Hibernate 代理加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7320023/