最近在搭建一个springmvc+hibernate+spring框架的时候,花了一个多月,一开始只是注重实现功能,根本没在意代码的简洁性和优化。后面优化代码的时候,发现hibernate的Session操作delete和update不行了,根本就无效,要执行session.flush()才能执行sql语句。session原理:其实我们执行session更新和删除操作的时候,不会立即执行,要执行flush才可执行。但是如果配置了事务管理,这件事就可以交给事务管理器去完成,在事务提交的时候执行自动执行flush语句。
为了确定是否是事务问题,我把事务配置注释掉了,问题还是原来那样子,所以我就一直去更改事务管理配置,更改了五种事务管理方法。一次又一次的检查,但是还是无效。确定了事务问题,但是事务配置有没有错误,奔溃了。
错误原因:是配置出现了问题:
<!-- 加载所有的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:config/spring/*.xml</param-value>
</context-param>
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:config/spring/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
一开始就加载了所以配置,后面servlet初始化的时候又加载了springmvc.xml。这本身就是不合理了的。但是主要问题不是这个。问题是:spring-mvc.xml由servlet加载的时候,
<!-- 扫描基础控制器注解-->
<context:component-scan base-package="com.tgb" />
如果一开始就注册所有的注解,那么,遇到@service的时候,事务配置就很可能无效,尤其是@Transactional一定失效。所以事务配置就不管用。
解决方案:分开加载控制器和其他注解。控制器的注解由springmvc.xml加载,
<!-- 扫描基础控制器注解-->
<context:component-scan base-package="com.tgb.controller" />
spring配置文件中,加载其他注解:
<context:component-scan base-package="com.tgb.*">
<context:exclude-filter type="regex" expression=".*controller$"/>
</context:component-scan>
<tx:annotation-driven transaction-manager="transactionManager" />
这样,事务配置就能起作用了。
其他失效情况:
一般是代码出现的小问题。delete和update只能对持久态的对象进行操作,所以要先查出对象,才能进行更新。
transient:是指数据还没跟数据库中的数据相对应。
一般是new出来的对象
persistent:是指数据跟数据库中的数据相对应,它的任何改变都会反映到数据库中。
执行完save的对象,查询出来的对象。
detached:是指数据跟数据库中的数据相对应,但由于session被关闭,它所做的修改不会对数据库的记录造成影响。
session关闭后。