我正在使用JPA / Hibernate。我注意到,当我持久化一个新对象时,我必须查找引用字段。例如,如果我与Person和Address有一对一的关系。我希望每个地址只能引用一个人。并且我知道人员的pimary密钥,我仍然需要在Person上查找以保留地址。
@Transactional
public void saveAddressFor( Long personId, <adddress_details> ) {
Address address = new Address();
address.setOwner( em.getReference( Person.class, personId ) );
address.setAddress( <address_details> );
em.persist( address );
}
我希望因为我知道Person PKEY,通过使用#getReference,我不需要查找它只是为了获取其PKEY来设置插入。但是当我检查SQL跟踪时,我发现在事务结束时它实际上会在执行INSERT之前查找Person。
有没有办法避免这种查找?这不是一个大问题,它只是不必要的,我想尽可能摆脱这些。
答案 0 :(得分:0)
您的使用是正确的。通常getReference()
只会为您提供一个参考对象,而不会转到DB。
如果您确实看到它从DB加载,很可能在您的代码中,您访问了person
的方法/属性,导致Hibernate执行延迟提取。 (还有另一种可能是Hibernate的错误,但我认为机会很低)
答案 1 :(得分:0)
以下hibernate属性无法做到这一点:
<property name="hibernate.jdbc.batch_size" value="150"/>
<property name="hibernate.order_inserts" value ="true"/>
为了对插入进行排序,出于某种原因,Hibernate将迭代它所持有的对象的所有实体字段(即使CascadeType为NONE)并在每个字段上调用#hashCode。调用#hashCode将导致从数据库加载引用代理。
对于4.2.4.Final,您可以在ActionQueue.java第799行中看到调用#findBatchNumber的代码。 #findBatchNumber的违规行号是856,此代码被称为:
Integer associationBatchNumber = entityBatchNumber.get( value );
在这种情况下,“value”将是Person引用。这会导致在其上调用#hashCode,这将要求从数据库加载它。