组件扫描
首先要做的事情是:您正在使用@Controller、@Service、@Repository 和@Autowired,但您不使用它们做任何事情。我推荐使用classpath scanning。从您的 spring 上下文文件中删除“testServiceDAO”和“testService”bean,并改为使用:
<context:component-scan base-package="com.test.spring.ws"/>
这将通过它们的注释找到并创建这些 bean,而不是要求您在 XML 中声明它们。将@Autowired 添加到服务中的testServiceDAO 字段和DAO 中的sessionFactory 字段。删除这些字段的设置器。他们不再需要了。组件扫描标签也会为你做自动装配。要使用 context 命名空间,您需要将其添加到您的根元素中。例如:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
交易管理
致use @Transactional,正如肖恩所说,你需要在你的spring上下文文件中添加一个元素:
<tx:annotation-driven/>
由于您的事务管理器 bean 被命名为“transactionManager”,它会自动找到它。您还需要将“tx”命名空间添加到您的根元素,所以它应该看起来像:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
为此,您需要从 DAO 方法中同时删除 session.beginTransaction() 和 session.close()。以这种方式打开您自己的事务是混合了程序化和声明性事务划分,而声明性方式通常更好。此外,您不应该永远在实际项目中关闭 DAO 中的会话。这会给你带来各种各样的麻烦。
异常处理
您的MySQLIntegrityConstraintViolationException,是一个特定于数据库的异常,将被Hibernate 捕获并包装在ConstraintViolationException 中,这就是您的DAO 的结果;但是,由于您的 DAO 现在是 @Repository,您可以从 Spring 的 exception translation 中受益。这样,Hibernate 异常将被 Spring 捕获并转换为 DataIntegrityViolationException。数据库异常处理总是很有趣!
会话管理
您使用的是OpenSessionInViewFilter 还是OpenSessionInViewInterceptor?如果是这样,Hibernate 会话会在第一次收到请求时打开,并在写入响应后关闭。如果不是,则会话直到事务开始(在 @Transactional 方法)才开始,并且在该事务完成时关闭。使用过滤器/拦截器,您可以在“视图”层中执行需要回调数据库的操作——特别是当您有渲染视图所需的延迟关系或延迟加载对象时。如果会话不可用——因为它只存在于事务服务方法的长度内——你不能在视图中做这些事情,你会得到臭名昭著的LazyInitializationException。
至于“发生异常后不刷新会话”错误,我没有立即看到任何让我认为应该发生的事情。也许您的 web 层 spring 上下文中的某些内容配置错误,或者您在 DAO 中直接处理事务和会话的方式可能存在一些奇怪的相互作用。