问题描述
在用springmvc时,用到了spring事务管理<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><propertyname="driverClassName"><value>${jdbc.driver}</value></property><propertyname="url"><value>${jdbc.url}</value></property><propertyname="username"><value>${jdbc.username}</value></property><propertyname="password"><value>${jdbc.password}</value></property><propertyname="maxActive"><value>${maxActive}</value></property><propertyname="maxWait"><value>${maxWait}</value></property><propertyname="maxIdle"><value>${maxIdle}</value></property><propertyname="removeAbandoned"><value>${removeAbandoned}</value></property><propertyname="removeAbandonedTimeout"><value>${removeAbandonedTimeout}</value></property><propertyname="validationQuery"><value>${validationQuery}</value></property><propertyname="defaultAutoCommit"><value>true</value></property></bean><!--配置Jdbc模板--><beanid="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate"><propertyname="dataSource"ref="dataSource"/></bean><!--配置事务管理器p:dataSource-ref="dataSource"/>--><beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><propertyname="dataSource"ref="dataSource"/></bean><!--通过AOP配置提供事务增强,让service包下所有Bean的所有方法拥有事务--><aop:configproxy-target-class="true"><aop:pointcutid="serviceMethods"expression="execution(*app.com.*.service..*.*(..))"/>*<aop:advisorpointcut-ref="serviceMethods"advice-ref="txAdvice"/></aop:config><tx:adviceid="txAdvice"transaction-manager="transactionManager"><tx:attributes><tx:methodname="add*"propagation="REQUIRED"rollback-for="Exception"/><tx:methodname="edit*"propagation="REQUIRED"rollback-for="Exception"/><tx:methodname="remove*"propagation="REQUIRED"rollback-for="Exception"/><tx:methodname="save*"propagation="REQUIRED"rollback-for="Exception"/><tx:methodname="update*"propagation="REQUIRED"rollback-for="Exception"/><tx:methodname="delete*"propagation="REQUIRED"rollback-for="Exception"/><tx:methodname="batchUpdate"propagation="REQUIRED"rollback-for="Exception"/><tx:methodname="*"read-only="true"/></tx:attributes></tx:advice>上面事务配置我理解的意思是:通过springaop配置让工程service包下的所有以add、edit、save、update等开头的方法对其自动的事务提交、回滚在service包下有个方法我是这样写的:packageapp.com.test.service;@RepositorypublicclassTestServiceImplimplementsTestService{@AutowiredprivateTestJdbcDAOtestJdbcDAO;publicvoidsaveTest()throwsException{Stringsql1="insertintoATTACHINFO(id,name)values(1,'test1')";testJdbcDAO.update(sql1);Stringsql2="insertintoATTACHINFO(id1,name)values(2,'test2')";//错误sql语句testJdbcDAO.update(sql2);}执行这个方法中,sql1是正确的,sql2是错误的,执行完在数据库中看到第一条数据插入进去了。我理解的是两条数据都不会入库,会进行事务回滚。这挺让我费解的,求大神指教
解决方案
解决方案二:
你第一次update的时候是一个完整的事务,执行完后就commit了,第二次update时是一个新的事务,和第一个事事务完全没关系
解决方案三:
那配置了spring事务管理有什么用?我把这个配置去掉,还是以上的结果
解决方案四:
引用1楼aazbc的回复:
你第一次update的时候是一个完整的事务,执行完后就commit了,第二次update时是一个新的事务,和第一个事事务完全没关系
那配置了spring事务管理有什么用?我把这个配置去掉,还是以上的结果
解决方案五:
maek一下看看其实我配置的就是都回滚,等大神,
解决方案六:
引用4楼boybaozi的回复:
maek一下看看其实我配置的就是都回滚,等大神,
你怎么配置的,让它们都回滚
解决方案七:
解决方案八:
rollback-for="Exception"去掉
解决方案九:
在JDBC中是通过Connection对象进行事务管理的,默认是自动提交事务,可以手工将自动提交关闭,通过commit方法进行提交,rollback方法进行回滚,如果不提交,则数据不会真正的插入到数据库中。Hibernate中是通过Transaction进行事务管理,处理方法与JDBC中类似。Spring中也有自己的事务管理机制,使用TransactionMananger进行管理,可以通过Spring的注入来完成此功能。
解决方案十:
断点到TransactionInterceptor类的invoke方法,再执行saveTest确认aop配置是否正确
解决方案十一:
是不是顺序写反了。。tx和aop
解决方案十二:
引用8楼baohuan_love的回复:
在JDBC中是通过Connection对象进行事务管理的,默认是自动提交事务,可以手工将自动提交关闭,通过commit方法进行提交,rollback方法进行回滚,如果不提交,则数据不会真正的插入到数据库中。Hibernate中是通过Transaction进行事务管理,处理方法与JDBC中类似。Spring中也有自己的事务管理机制,使用TransactionMananger进行管理,可以通过Spring的注入来完成此功能。
那把defaultAutoCommit设置为false后,在代码中每次保存操作都要用commit方法,那么配置txaop的的增强事务有什么作用?
解决方案十三:
引用10楼Gu31415的回复:
是不是顺序写反了。。tx和aop
不是顺序写反了的问题的
解决方案十四:
引用9楼whos2002110的回复:
断点到TransactionInterceptor类的invoke方法,再执行saveTest确认aop配置是否正确
没进入断点;<aop:pointcutid="serviceMethods"expression="execution(*app.com.*.service..*.*(..))"/>*对应扫描包packageapp.com.test.service;应该没问题吧;还需要配置什么?
解决方案十五:
如果事务配置成功的话,方法里两条insert都不会成功执行的,是不是扫描包的问题?在spring和springMVC配置文件中,扫描包是怎么配置的?还有web容器启动的时候,这两个配置文件的加载顺序是怎样的?
解决方案:
扫描包的配置execution(*app.com.*.service..*.*(..))改为execution(*app.com.*.service..*(..))试试,是不是多了一层
解决方案:
引用15楼jiiiang400的回复:
扫描包的配置execution(*app.com.*.service..*.*(..))改为execution(*app.com.*.service..*(..))试试,是不是多了一层
改成你这样也没用啊
解决方案:
Spring的事务没有问题,既然不起作用,只能是你的配置有问题!对于这一串execution,对照着Spring官网配置,能出问题吗?另外,都啥年代了,还用这种方式来配置事务!建议使用注解方式配置事务,简单、快捷、灵活!
解决方案:
虽然没有得到具体是什么原因,但还是非常感谢大家的帮助,这个问题本人已经解决了;原因是因为我这里是用来springmvc,在配spring注解的时候出现问题如下:在主容器中(applicationContext.xml),将Controller的注解排除掉在springMVC配置文件中将Service注解给去掉(我之前没加这个)<context:component-scanbase-package="com"><context:include-filtertype="annotation"expression="org.springframework.stereotype.Controller"/><context:exclude-filtertype="annotation"expression="org.springframework.stereotype.Service"/></context:component-scan>因为spring的context是父子容器,所以会产生冲突,由ServletContextListener产生的是父容器,springMVC产生的是子容器,子容器Controller进行扫描装配时装配了@Service注解的实例,而该实例理应由父容器进行初始化以保证事务的增强处理,所以此时得到的将是原样的Service(没有经过事务加强处理,故而没有事务处理能力。还有一种方式是将service层改用xml配置,其实这样做也是变相的让springmvc无法扫描service,而只能依赖父窗口也就是ServletContextListener来进行初始化,这样同样被赋予了事务性。
解决方案:
引用17楼crazypandariy的回复:
Spring的事务没有问题,既然不起作用,只能是你的配置有问题!对于这一串execution,对照着Spring官网配置,能出问题吗?另外,都啥年代了,还用这种方式来配置事务!建议使用注解方式配置事务,简单、快捷、灵活!
注解?你确定spring注解配置事务比这种aop的方式更加方便?这个我到是不赞同!
解决方案:
很明显,实际中都是在xml中配置事物