使用Hibernate(JPA)时,如果我执行以下调用:
MyParent parent = em.getReference("myId");
parent.getAListMappedAsOneToMany().add(record)
record.setParent(parent);
有任何性能问题吗?
我的想法是getReference
没有加载实体,getAListeMappedAsOneToMany().add
不需要加载列表,因为它被定义为懒惰提取。
getAListMappedAsOneToMany
可以返回一个非常大的列表(如果它真的被访问过(通过调用get
或size
方法)。
您能否确认此类代码没有性能问题?
答案 0 :(得分:2)
getReference()
不会转到数据库,并返回代理。但是如果在代理上调用方法,它会初始化代理并从数据库中获取实体数据。因此,当您在实体上致电getAListMappedAsOneToMany()
时,通过调用getReference()
代替find()
,您无法获得任何收益。
同样,列表是懒惰加载的。这意味着它只会在您调用方法时加载。你确实在其上调用了一个方法:add()
。因此,列表中元素的数据也会从数据库中加载。
在开发中启用SQL日志记录,以查看和理解Hibernate执行的所有查询。
如果您想避免加载列表,请用
替换您的代码MyParent parent = em.getReference("myId");
record.setParent(parent);
这不会从数据库中加载任何内容,并且会使关联持久化,因为Record.parent是关联的所有者方。但请注意,如果之前已加载父对象,这也将使您的内存中对象图不一致。
答案 1 :(得分:1)
getReference()
非常有用。例如,当实体A引用实体B并且您想将b设置为A的B时,则getReference()
就是您所需要的。
但在您的情况下,当您获得代理对象时,您会立即尝试联系其中一个成员。 (aListMappedAsOneToMany
)因此,这将导致整个parent
对象将从db加载。
确实,当您getAListMappedAsOneToMany().add(record)
时,只有在设置inverse="true"
您可以从以下网址了解有关效果的更多信息: http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html#performance-collections-mostefficentinverse