DAO、Spring 和 Hibernate

Posted

技术标签:

【中文标题】DAO、Spring 和 Hibernate【英文标题】:DAO, Spring and Hibernate 【发布时间】:2011-01-27 16:02:03 【问题描述】:

如有错误请指正。

现在,当我们将 Spring DAO 用于 ORM 模板时,当我们使用 @Transactional 属性时, 当方法被外部调用时,我们无法控制事务和/或会话。

延迟加载可以节省资源 - 对数据库的查询更少,将所有集合保存在应用内存中的内存更少。

因此,如果lazy=false,那么如果链接集中有 10,000 条记录,那么所有相关的集合都将被获取。

现在,我在 DAO 类中有一个方法,它应该返回一个用户对象。 它具有代表数据库链接表的集合。 我需要通过 id 获取一个对象,然后查询它的集合。

当我尝试访问此 DAO 方法返回的链接集合时,发生 Hibernate“无法延迟初始化集合”异常。

请解释一下,这里有什么解决方法?

更新:好的,我问你这个。 DAO 是一个抽象层,因此方法“getUserById(Integer id)”应该返回一个对象。

如果在某些情况下我需要用户对象的这些链接集合,而在其他情况下我需要这些集合,该怎么办?

只有两种方法: 1)延迟加载=假 2) 创建不同的方法:getUserByIdWithTheseCollections()、getUserByIdWithOtherCollections() 并在这些方法中使用您的方法?

我的意思是只有两种方法,没有更好的方法?

更新 2:请解释一下,什么会让我明确使用 SESSIONFACTORY? 它在实践中看起来如何?我们创建一个 DAO 对象的实例, 然后用会话工厂注入它,这意味着两个结果 对 DAO 的方法调用将在同一个事务中运行? 在我看来,无论如何,DAO 与使用它的类是分离的!

逻辑和事务都封装在 DAO 中,对吧?

【问题讨论】:

【参考方案1】:

您可以在事务中获取链接的集合以在事务中加载它:

User user = sessionFactory.getCurrentSession().get(User.class, userId);
user.getLinkedCollection().size();
return user;

正如 BalusC 所指出的,您可以使用 Hibernate.initialize() 而不是 size()。这样干净多了。

那么当你返回这样一个实体时,惰性字段已经被初始化了。

回复您的 PS - 在服务级别(而不是 DAO)级别使用事务是否可行?似乎是,因为在单独的事务中进行每个 DAO 调用似乎是一种浪费(并且可能是不正确的)。

【讨论】:

@Konrad Garus 请看我的问题后记,这里的文字可读性较差,所以我在那里问你。【参考方案2】:

我发现最好把@Transactional放在服务层,而不是DAO层。否则,你所有的 DAO 调用都在单独的休眠会话中——所有对象相等的东西都不起作用。

【讨论】:

这是在使用 SpringDAO 时处理它的好方法。【参考方案3】:

在我看来,解决此问题的最佳方法是在每请求会话模型中设计应用程序。然后,如果您甚至有一个从 DAO 获取的对象,在您的 OSIV 模式起作用之前,您可以在应用程序的任何地方安全地使用该对象,即使在视图中也无需打扰这些东西。这可能是那些提议的更好的解决方案,因为:

    Hibernate.initialize() 或 size 是一种非常人为的解决方法 - 如果您希望初始化具有不同集合的用户,您会编写另一种获取用户的方法吗? 服务层事务模型是可以的,但是当你想从服务层提取对象以在控制器或视图中使用时,同样的问题会出现

【讨论】:

【参考方案4】:

您可以执行以下操作:

public User getByUserId(Long id, String ... fetch) 
    Criteria criteria = createCriteria();

    if (fetch != null) 
        for (String fieldName : fetch) 
             criteria.setFetchMode(fieldName, FetchMode.JOIN); // fetch these fields eagerly
        
    
    return criteria.add(Restrictions.eq("id", id)).list();

【讨论】:

以上是关于DAO、Spring 和 Hibernate的主要内容,如果未能解决你的问题,请参考以下文章

Spring框架中的DAO和Service层是什么?

Spring Framework 中的 DAO、DTO 和 Service 层是啥?

spring配置连接池和dao使用jdbcTemplate

Spring 和 Hibernate:DAO 模式。如何解决 LazyInitializationException

Spring aop 拦截不到Dao

DAO、Spring 和 Hibernate