Spring中的DAO和Service层:会话管理

3
我理解DAO和服务层互连的原则是正确的吗? DAO从数据库中提取基础对象,例如通过id。
服务层使用DAO对象,并且可以在一个函数中调用DAO的多个方法。 因此,服务层需要:
1. 实例化DAO实现对象 2. 调用所需数量的DAO方法
如果DAO实现了接口,那么DAO接口是否必须有一个setSessionFactory()方法?
如何在Spring中声明标记:
1. DAO对象 2. 服务层方法和类作为整体
以便得到所需的结果?
3个回答

7
我很惊讶没有其他人特别提到这一点,但是像 setSessionFactory() 这样的实现细节不应该出现在你的 DAO 接口中。通过向 DAO 接口添加一个 Hibernate 特定的类,你将直接将 DAO 与 Hibernate 绑定在一起。
使用接口和依赖注入的目的是允许您更改某个层(例如 DAO)的实现细节(例如,您使用的 ORM 解决方案或数据来自 Web 服务还是数据库),而不会影响其他层。
如果您在 DAO 接口中添加了 setSessionFactory,那么使用此 DAO 的所有其他层都将意识到和绑定在一起,即数据访问是通过 Hibernate 完成的。这与使用接口和依赖注入所要实现的相反。

2
+1 我暗示了这一点,但你说出来很好。我的一个 DAO 通常看起来像这样 class UserHibernateDAO extends HibernateDAO implements UserDAO,其中 HibernateDAO 是一个抽象类。然后,如果我需要一个 FileDAO,我只需交换掉模板即可。 - Jeremy
虽然这是暗示,但我认为强调一下很重要。我把“特别是”改成了“没有人提到过这点”,我意识到这只是一个暗示 :) - matt b
哦,没有关系。我同意明确地说是很重要的。;-) - Jeremy

4
对于我的项目,我编写了一个基类,其中包含一个名为setSessionFactory()的方法,所有DAO都继承自该基类。然后,我使用Spring将我的DAO与其连接起来,以便将SessionFactory注入到每个DAO中。
Hibernate有一个SessionFactory.getCurrentSession()方法,因此如果您将SessionFactory注入到DAO中并使用该方法,则Session的范围将根据您的事务管理机制进行定义。
这意味着,如果您有一个如下所示的方法:
@Transactional
public void doSomething(){
    dao1.makeCall();
    dao2.makeOtherCall();
}

当您构造每个DAO时注入的SessionFactory将使用相同的Session。但仅限于该事务的范围内。

@Jer 在你的情况下,DAO方法(dao1)也需要有@Transactional属性吗? - EugeneP
1
不会。DAO将使用 SessionFactory.getCurrentSession() 来检索与当前事务范围相关的 Session - Jeremy
@EugeneP - 通常你会使用@Transactional注解来标记你的服务类和服务方法。如果在序列化对象时出现了懒加载异常,请查看OpenSessionInViewFilter以保持整个Web请求的事务开启。http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.html - leedm777
如果我只需要一个复杂的结构,比如不同表格的组合和联接获取,我只需要向DAO添加一个新方法而不使用Service层吗? - EugeneP
@Eugene- 这取决于你需要什么。如果你需要从几个DAO获取数据,并且将所有内容包装成单个事务是有意义的,那么你将编写一个服务方法来调用DAO上的方法。如果你要跳过服务层,你可以在DAO方法上放置@Transactional。我认为这不会对其他事务造成任何伤害,因为在另一个事务内打开事务没有影响。也就是说,第二个事务不会打开。 - Jeremy
显示剩余2条评论

2
  • 将事务和会话管理留给Spring(通过内置的事务管理器)。
  • 在DAO中使用sessionFactory.getCurrentSession()来访问会话。
  • 在DAO中注入SessionFactory
  • 将DAO作用域设为singleton
  • 使用声明式事务(可以使用<aop@Transactional)。
  • 将DAO通过常规依赖注入注入到服务对象中。同样地,服务类也会在需要它们时进行注入。

服务层 - 它如何提取 DAO 对象?也使用 ApplicationContext 吗? - EugeneP
另外,关于单例模式,这是同样的问题。如果它是从Spring获取的,则将是单例模式,否则请解释您的意思。 - EugeneP
@Eugene - Spring构造的对象默认情况下是单例的(大多数情况下),但是SessionFactory.getCurrentSession()方法只会在事务范围内首次调用时返回一个新的Session。否则,在事务结束之前,不管哪个类获取了Session,它都将继续返回相同的Session - Jeremy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接