第一節講述了不一樣service之間事務的傳播,通過小實驗,還原了spring的事務傳播結論,這期實驗下service中開啓新線程後,事務如何傳播java
首先是controller發起請求:spring
@RequestMapping(value="/test2") public void insert2() { System.out.println("---------spring mvc update---------"); userService.update2(111,"aaaazz"); System.out.println("---------spring mvc all---------"); }
userServiceImplapache
@Override @Transactional public void update2(int id,String username) { System.out.println("---------UserServiceImpl updateAge start---------"); updateAge(id); System.out.println("---------UserServiceImpl updateAge end---------"); MyThread thread = new MyThread(scoreService); thread.start(); // int i = 1 / 0; System.out.println("---------UserServiceImpl method over---------"); }
涉及的內部類:session
class MyThread extends Thread{ IScoreService scoreService; public MyThread (IScoreService scoreService){ this.scoreService = scoreService; } @Override public void run() { System.out.println("---------scoreService updateScore start---------"); this.scoreService.updateScore(1); System.out.println("---------scoreService updateScore end---------"); } }
scoreServiceImplmybatis
@Override @Transactional public void updateScore(int id) { scoreDao.updateScore(id); // try{ int i = 1 / 0; //exception測試註釋 i = 1; // } catch (Exception e){ // e.printStackTrace(); // } }
1:userServiceImpl和scoreServiceImpl都打開事務mvc
日誌輸出:app
---------spring mvc update--------- [DEBUG] 2018-05-23 20:44:38,367 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:243) Returning cached instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' [DEBUG] 2018-05-23 20:44:38,370 method:org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(AbstractFallbackTransactionAttributeSource.java:107) Adding transactional method 'UserServiceImpl.update2' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' [DEBUG] 2018-05-23 20:44:38,374 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:243) Returning cached instance of singleton bean 'transactionManager' [DEBUG] 2018-05-23 20:44:38,383 method:org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:366) Creating new transaction with name [com.paic.ssm.user.service.impl.UserServiceImpl.update2]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' [DEBUG] 2018-05-23 20:44:38,384 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:204) Acquired Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@139b811] for JDBC transaction [DEBUG] 2018-05-23 20:44:38,391 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:221) Switching JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@139b811] to manual commit ---------UserServiceImpl updateAge start--------- 20:44:38.401 [http-bio-8080-exec-9] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession 20:44:38.408 [http-bio-8080-exec-9] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@195fbac] 20:44:38.458 [http-bio-8080-exec-9] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@139b811] will be managed by Spring 20:44:38.461 [http-bio-8080-exec-9] DEBUG c.p.ssm.user.dao.IUserDao.updateAge - ooo Using Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@139b811] 20:44:38.467 [http-bio-8080-exec-9] DEBUG c.p.ssm.user.dao.IUserDao.updateAge - ==> Preparing: update user_t set age = ? 20:44:38.644 [http-bio-8080-exec-9] DEBUG c.p.ssm.user.dao.IUserDao.updateAge - ==> Parameters: 111(Integer) [DEBUG] 2018-05-23 20:44:38,650 method:com.alibaba.druid.pool.PreparedStatementPool.put(PreparedStatementPool.java:123) {conn-10010, pstmt-20000} enter cache 20:44:38.650 [http-bio-8080-exec-9] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@195fbac] ---------UserServiceImpl updateAge end--------- ---------UserServiceImpl method over--------- ---------scoreService updateScore start--------- [DEBUG] 2018-05-23 20:44:38,652 method:org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:753) Initiating transaction commit [DEBUG] 2018-05-23 20:44:38,653 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:243) Returning cached instance of singleton bean 'transactionManager' [DEBUG] 2018-05-23 20:44:38,653 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DataSourceTransactionManager.java:267) Committing JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@139b811] [DEBUG] 2018-05-23 20:44:38,653 method:org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:366) Creating new transaction with name [com.paic.ssm.user.service.impl.ScoreServiceImpl.updateScore]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' [DEBUG] 2018-05-23 20:44:38,654 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:204) Acquired Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1876493] for JDBC transaction [DEBUG] 2018-05-23 20:44:38,654 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:221) Switching JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1876493] to manual commit 20:44:38.655 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession 20:44:38.655 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b63214] 20:44:38.655 [Thread-2] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1876493] will be managed by Spring 20:44:38.655 [Thread-2] DEBUG c.p.s.user.dao.IScoreDao.updateScore - ooo Using Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1876493] 20:44:38.655 [Thread-2] DEBUG c.p.s.user.dao.IScoreDao.updateScore - ==> Preparing: update score_t set score = ? 20:44:38.655 [Thread-2] DEBUG c.p.s.user.dao.IScoreDao.updateScore - ==> Parameters: 1(Integer) [DEBUG] 2018-05-23 20:44:38,656 method:com.alibaba.druid.pool.PreparedStatementPool.put(PreparedStatementPool.java:123) {conn-10009, pstmt-20001} enter cache 20:44:38.656 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b63214] [DEBUG] 2018-05-23 20:44:38,656 method:org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:753) Initiating transaction commit [DEBUG] 2018-05-23 20:44:38,656 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DataSourceTransactionManager.java:267) Committing JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1876493] 20:44:38.732 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b63214] 20:44:38.732 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b63214] [DEBUG] 2018-05-23 20:44:38,734 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doCleanupAfterCompletion(DataSourceTransactionManager.java:325) Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1876493] after transaction [DEBUG] 2018-05-23 20:44:38,734 method:org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(DataSourceUtils.java:327) Returning JDBC Connection to DataSource ---------scoreService updateScore end--------- 20:44:38.819 [http-bio-8080-exec-9] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@195fbac] 20:44:38.819 [http-bio-8080-exec-9] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@195fbac] [DEBUG] 2018-05-23 20:44:38,820 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doCleanupAfterCompletion(DataSourceTransactionManager.java:325) Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@139b811] after transaction [DEBUG] 2018-05-23 20:44:38,821 method:org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(DataSourceUtils.java:327) Returning JDBC Connection to DataSource ---------spring mvc all---------
能夠看到,兩個方法均新建了新的事務,說明二者並非共享同一事務ide
2:userServiceImpl打開事務,scoreServiceImpl關閉事務測試
通過試驗,發現userServiceImpl開啓了新的事務,而scoreServiceImpl並未開啓事務。。。ui
繼續測試回滾
僅打開scoreServiceImpl的異常測試代碼,而且不捕獲異常,輸出以下:
eb.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:921) Last-Modified value for [/tx-spread/login/test2.do] is: -1 ---------spring mvc update--------- [DEBUG] 2018-05-23 20:58:39,560 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:243) Returning cached instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' [DEBUG] 2018-05-23 20:58:39,566 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:243) Returning cached instance of singleton bean 'transactionManager' [DEBUG] 2018-05-23 20:58:39,572 method:org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:366) Creating new transaction with name [com.paic.ssm.user.service.impl.UserServiceImpl.update2]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' [DEBUG] 2018-05-23 20:58:39,573 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:204) Acquired Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@150d517] for JDBC transaction [DEBUG] 2018-05-23 20:58:39,578 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:221) Switching JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@150d517] to manual commit ---------UserServiceImpl updateAge start--------- 20:58:39.584 [http-bio-8080-exec-6] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession 20:58:39.589 [http-bio-8080-exec-6] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@15f4f4d] 20:58:39.633 [http-bio-8080-exec-6] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@150d517] will be managed by Spring 20:58:39.635 [http-bio-8080-exec-6] DEBUG c.p.ssm.user.dao.IUserDao.updateAge - ooo Using Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@150d517] 20:58:39.639 [http-bio-8080-exec-6] DEBUG c.p.ssm.user.dao.IUserDao.updateAge - ==> Preparing: update user_t set age = ? 20:58:39.774 [http-bio-8080-exec-6] DEBUG c.p.ssm.user.dao.IUserDao.updateAge - ==> Parameters: 111(Integer) [DEBUG] 2018-05-23 20:58:39,778 method:com.alibaba.druid.pool.PreparedStatementPool.put(PreparedStatementPool.java:123) {conn-10010, pstmt-20000} enter cache 20:58:39.779 [http-bio-8080-exec-6] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@15f4f4d] ---------UserServiceImpl updateAge end--------- ---------UserServiceImpl method over--------- ---------scoreService updateScore start--------- [DEBUG] 2018-05-23 20:58:39,781 method:org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:753) Initiating transaction commit [DEBUG] 2018-05-23 20:58:39,782 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DataSourceTransactionManager.java:267) Committing JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@150d517] [DEBUG] 2018-05-23 20:58:39,782 method:org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:243) Returning cached instance of singleton bean 'transactionManager' [DEBUG] 2018-05-23 20:58:39,784 method:org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:366) Creating new transaction with name [com.paic.ssm.user.service.impl.ScoreServiceImpl.updateScore]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' [DEBUG] 2018-05-23 20:58:39,784 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:204) Acquired Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@190f65c] for JDBC transaction [DEBUG] 2018-05-23 20:58:39,784 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:221) Switching JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@190f65c] to manual commit 20:58:39.785 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession 20:58:39.785 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@cc6826] 20:58:39.785 [Thread-2] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@190f65c] will be managed by Spring 20:58:39.785 [Thread-2] DEBUG c.p.s.user.dao.IScoreDao.updateScore - ooo Using Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@190f65c] 20:58:39.785 [Thread-2] DEBUG c.p.s.user.dao.IScoreDao.updateScore - ==> Preparing: update score_t set score = ? 20:58:39.786 [Thread-2] DEBUG c.p.s.user.dao.IScoreDao.updateScore - ==> Parameters: 1(Integer) [DEBUG] 2018-05-23 20:58:39,787 method:com.alibaba.druid.pool.PreparedStatementPool.put(PreparedStatementPool.java:123) {conn-10009, pstmt-20001} enter cache 20:58:39.788 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@cc6826] [DEBUG] 2018-05-23 20:58:39,788 method:org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:844) Initiating transaction rollback [DEBUG] 2018-05-23 20:58:39,788 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doRollback(DataSourceTransactionManager.java:282) Rolling back JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@190f65c] 20:58:39.839 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization rolling back SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@cc6826] 20:58:39.839 [Thread-2] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@cc6826] [DEBUG] 2018-05-23 20:58:39,840 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doCleanupAfterCompletion(DataSourceTransactionManager.java:325) Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@190f65c] after transaction [DEBUG] 2018-05-23 20:58:39,840 method:org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(DataSourceUtils.java:327) Returning JDBC Connection to DataSource Exception in thread "Thread-2" java.lang.ArithmeticException: / by zero at com.paic.ssm.user.service.impl.ScoreServiceImpl.updateScore(ScoreServiceImpl.java:27) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at com.sun.proxy.$Proxy17.updateScore(Unknown Source) at com.paic.ssm.user.service.impl.MyThread.run(UserServiceImpl.java:103) 20:58:39.933 [http-bio-8080-exec-6] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@15f4f4d] 20:58:39.933 [http-bio-8080-exec-6] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@15f4f4d] [DEBUG] 2018-05-23 20:58:39,934 method:org.springframework.jdbc.datasource.DataSourceTransactionManager.doCleanupAfterCompletion(DataSourceTransactionManager.java:325) Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@150d517] after transaction [DEBUG] 2018-05-23 20:58:39,935 method:org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(DataSourceUtils.java:327) Returning JDBC Connection to DataSource ---------spring mvc all---------
userServiceImpl事務提交了,scoreServiceImpl回滾了(日誌拋出挺長的),和DB結果一致,因爲兩個方法位於不一樣的事務中,也很符合預期
當scoreServiceImpl關閉事務,發現userServiceImpl事務回滾,而是scoreServiceImpl並未回滾,也符合預期
因爲兩個service位於不一樣的事務,因此提交和回滾均是按照自身的事務規則。
從實驗能夠看出,若是在事務處理的方法中開啓了子線程,事務是不會傳播的,子線程的事務由其自己調用的方法的事務決定的,若是子線程調用的方法無事務,那麼其就以無事務方式運行