hibernate dao 设计问题

Posted

技术标签:

【中文标题】hibernate dao 设计问题【英文标题】:hibernate dao design question 【发布时间】:2011-03-24 01:55:23 【问题描述】:

我希望在我的休眠应用程序中创建一个通用 DAO 来处理 CRUD。我的实体的大多数关联都是 LAZY fetching。但是我发现为了让休眠尽可能高效地使用 SELECT,我必须在我的 DAO 上创建多个方法。这就是我的意思:

实体 A 有两个关联。有时我想在不加载关联的情况下检索这个实体,有时我希望它完全填充,所以我在 DAO 上放置了两种方法:

getWhatever()
getWhateverWithLoadedAssociations()

我会有两个不同的查询,一个没有 join fetch,另一个有 join fetch。结果是无论它是否 LAZY,hibernate 总是只进行一次选择,因为我知道我想要提前获得什么。

这样做的问题是,在保存一个或两个 SELECT 时,由于方法的数量,它增加了复杂性。

所以这是极端的吗?我是否应该只使用 getWhatever() 并在我需要关联数据时让 hibernate 进行另一个选择,即使我本可以避免不执行该选择?

我希望这不会太令人困惑。我正在尝试计算由于延迟加载而导致的 SELECTS 数量与代码复杂性的成本

谢谢

【问题讨论】:

【参考方案1】:

所以你的问题是你可能有太多的方法?我认为这是对的,因为这些方法做不同的事情。

如果你想减少数量并且你正在使用 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();

【讨论】:

【参考方案2】:

我认为这可能属于过早优化。换句话说,除非您确定那里存在性能问题,否则不要这样做。

暂时让 Hibernate 进行延迟获取,如果应用程序太慢,您可以开始仅在需要的地方添加这些方法。

【讨论】:

【参考方案3】:

所以这是极端的吗?我是否应该只使用 getWhatever() 并在我需要关联数据时让 hibernate 进行另一个选择,即使我本可以避免不执行该选择?

如果您启用了惰性关联/获取,那么如果一段不需要关联的代码调用 getWhatever()getWhateverWithLoadedAssociations() 有什么区别?它应该产生相同数量的 SQL 查询。

如果您只有一个 getWhatever() 方法,请检查可能性:

    一段代码没有访问关联 - 没有触发用于加载关联的 SQL 查询 一段代码确实访问了关联 - 触发了用于加载关联的 SQL 查询。

在任何一种情况下,关联只会在需要时加载。

延迟加载的目的是让你不必担心这种事情——如果调用DAO方法的代码访问了关联,那么它就会被加载;如果不是,则不是。

【讨论】:

我猜这个问题与使用单个查询和获取主对象和关联的连接时的性能差异有关。这比 Hibernate 所做的多个查询要好。【参考方案4】:

恕我直言,我将在通用 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

【讨论】:

【参考方案5】:

你可以有一个通用的(在基类中)dao 方法:

public void initialize(Object entity);

你打电话给Hibernate.initialize(entity)的地方;

【讨论】:

【参考方案6】:

在我看来,是的,你太极端了。

除非您正在开发包含数千个此类查询的批处理过程,否则执行单个查询与 hibernate 在延迟加载时执行的查询之间没有太大区别。

无论如何,如果您已经确认担心应用程序的性能,那么您刚才提出的做法并不是一个坏习惯。

【讨论】:

以上是关于hibernate dao 设计问题的主要内容,如果未能解决你的问题,请参考以下文章

hibernate dao 设计问题

Hibernate 中的事务管理与 DAO 设计模式

求教第一个hibernae程序的配置文件hibernate.cfg.xml出错了,求帮忙解决,如下

Hibernae

基于Spring4+Hibernate4的通用数据访问层(Dao层)设计与实现!

Hibernaate 详解