我希望在我的hibernate应用程序中创建一个通用的DAO来处理CRUD。我的实体拥有大多数关联作为LAZY获取。但我发现为了让hibernate尽可能高效,我必须在我的DAO上创建多个方法。这就是我的意思:
实体A有两个关联。有时候我想在不加载关联的情况下检索这个实体,有时候我希望它完全填充,所以我在DAO上放了两个方法:
getWhatever()
getWhateverWithLoadedAssociations()
我有两个不同的查询,一个没有连接提取,另一个连接提取。结果是hibernate总是做一次选择,无论它是否为LAZY,因为我知道我想要的是什么。
这个问题是,在保存一两个SELECT时,由于方法的数量而增加了复杂性。
这是极端的吗?我应该只使用getWhatever()并让hibernate在我需要关联数据时再做一次选择,即使我可以保存而不执行SELECT吗?
我希望这不会太混乱。我试图计算由于延迟加载而导致的SELECTS数量与代码复杂性相比的成本
感谢
答案 0 :(得分:2)
所以你的问题是你可能有太多的方法?我认为这是正确的,因为这些方法做了不同的事情。
如果你想减少数量并且你正在使用HQL,你可以在方法中添加一个参数,说明你是否想要加入获取关系:
getWhatever(WhateverFetchMode f)
其中f可以是布尔值,或者是返回字符串的HQL片段的对象,该片段为您提供要获取的关系。
public List<MyObject> getList(boolean fetchProp1) {
return em.createQuery("select r" +
"from Object as r " +
fetchProp1 ? "left join fetch r.prop1 " : "")
.getResultList();
}
或
public List<MyObject> getList(WhateverFetchMode fetchProp1) {
return em.createQuery("select r" +
"from Object as r " +
fetchProp1.toHql()) // This returns the right join fetch
.getResultList();
}
答案 1 :(得分:2)
我认为这可能有资格成为过早优化。换句话说,除非你确定那里存在性能问题,否则不要这样做。
现在让Hibernate执行其延迟抓取,如果应用程序太慢,您可以开始只在需要的地方添加这些方法。
答案 2 :(得分:2)
这是极端的吗?我应该只使用getWhatever()并让hibernate在我需要关联数据时再做一次选择,即使我可以保存而不执行SELECT吗?
如果启用了延迟关联/提取,那么如果一段不需要关联的代码调用getWhatever()
或getWhateverWithLoadedAssociations()
,会有什么区别?它应该导致相同数量的SQL查询。
如果您只有一个getWhatever()
方法,请检查可能性:
在任何一种情况下,只在需要时加载关联。
延迟加载的目的是让你不必担心这种类型的事情 - 如果调用DAO方法的代码访问关联,那么它就被加载了;如果不是,它不是。
答案 3 :(得分:1)
恕我直言,我将在通用DAO中添加以下一些方法:
findById(Id id);//lazy load
loadTree(Id id);//load full graph of the entity
load(Id id, String... includePaths);// just load some associations of the entity
答案 4 :(得分:0)
你可以有一个共同的(在基类中)dao方法:
public void initialize(Object entity);
您致电Hibernate.initialize(entity)
;
答案 5 :(得分:0)
在我看来,是的,你是极端的。
除非您正在使用这些查询的thousends开发批处理过程,否则执行单个查询与hibernate在加载懒惰时执行的查询之间没有太大区别。
无论如何,如果您已经确认了对应用程序性能的担忧,那么您提出的建议并不是一种糟糕的做法。