仅使用主键的Hibernate代理加载

时间:2011-09-06 12:35:43

标签: hibernate

我们有以下关系:
汽车由一个人拥有。
一个人可以拥有很多车。

这是汽车的映射:

<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)

我想根据他的身份为特定的人插入一辆车。 现在我的代码看起来像这样:

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);
}

此方法的缺点

  • 所有Person对象正在加载,即使我需要从SQL视图中只是他的id
  • 如果人员的映射进展(如延迟加载设置为false等),则操作可以生成更多2个查询。

我的实际解决方法: 它是将外键直接映射到整数

  <property column="id_person" name="idPerson" />

此解决方案不是面向对象且不太美观。 如果明天我需要检索汽车的所有者,我必须像以前一样重新映射人物对象并更新= false

是否有可能只加载一个代理人他的id将导致查询 验证此人是否与他的主键一起存在,并且如果他们被调用,则可选择以惰性模式加载其他字段。

我已尝试过session.load,但这不是解决方案。该对象永远不会为null(没有查询测试它的存在)或在您访问其他字段之前不会抛出任何异常 从数据库中加载实际对象。

1 个答案:

答案 0 :(得分:4)

是的,这正是session.loadEntityManager.getReference,如果使用JPA)的目的。它假定实体存在,它将代理加载到对象。

当然,如果在提交时,外键约束因为该人实际上不存在而中断,则可能会有异常。但是如果其他事务在提交之前删除了该人,那么您可能还会使用Session.get

如果你真的想检查这个人是否存在,请执行一个专门的查询,只返回一个布尔值(或一个计数),当你知道该人存在时使用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
}