组件扫描
首先要明确的是:你正在使用 @Controller、@Service、@Repository 和 @Autowired,但却没有使用它们。我建议使用 类路径扫描。从 Spring 上下文文件中删除 "testServiceDAO" 和 "testService" beans,改为使用以下内容:
<context:component-scan base-package="com.test.spring.ws"/>
这将通过它们的注释来查找和创建这些bean,而不需要您在XML中声明它们。在您的服务中将testServiceDAO
字段和DAO中的sessionFactory
字段添加@Autowired注释。移除这些字段的setter方法,它们不再需要了。component-scan标签也会为您执行自动装配。要使用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">
事务管理
如Sean所说,要使用@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的
异常转换。使用此选项,Spring将捕获Hibernate异常并将其翻译为
DataIntegrityViolationException。数据库异常处理总是有趣!
会话管理:
您是否正在使用
OpenSessionInViewFilter或
OpenSessionInViewInterceptor?如果是,则Hibernate会话在首次收到请求时打开,并在响应编写后关闭。否则,会话不会开始,直到事务开始(在@Transactional方法中),并在该事务完成时关闭。使用过滤器/拦截器时,您可以在“视图”层中执行需要回调数据库的操作,特别是当您需要为呈现视图而需要惰性关系或惰性加载对象时。如果会话不可用-如果它仅存在于事务服务方法的长度中,则无法在视图中执行这些操作,您将收到臭名昭着的
LazyInitializationException。
至于您遇到的“在异常发生后不要刷新会话”错误,我没有立即看到任何可能导致这种情况发生的原因。也许您Web层Spring上下文中的某些配置不正确,或者在DAO中直接处理事务和会话的方式存在某些奇怪的相互作用。