我们有以下关系:
汽车由一个人拥有。
一个人可以拥有很多车。
这是汽车的映射:
<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);
}
此方法的缺点:
我的实际解决方法: 它是将外键直接映射到整数
<property column="id_person" name="idPerson" />
此解决方案不是面向对象且不太美观。 如果明天我需要检索汽车的所有者,我必须像以前一样重新映射人物对象并更新= false
是否有可能只加载一个代理人他的id将导致查询 验证此人是否与他的主键一起存在,并且如果他们被调用,则可选择以惰性模式加载其他字段。
我已尝试过session.load,但这不是解决方案。该对象永远不会为null(没有查询测试它的存在)或在您访问其他字段之前不会抛出任何异常 从数据库中加载实际对象。
答案 0 :(得分:4)
是的,这正是session.load
(EntityManager.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
}