spring springboot mybatis 事务配置 Transactional的Propagation 开启事务 关闭事务_globalcoding
单元测试时,发现默认是使用事务。想要关闭事务,使用:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
做单元测试的时候,发现默认是使用事务的。代码和日志如下:
@RunWith(SpringRunner.class) @MybatisPlusTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @Rollback(false) public class T1 { @Autowired private XxxMapper xxxMapper; @Test public void t1() { int i = 0; ListxxxDoList = getData(); System.out.println("我的打印:插入数量 count:" + xxxDoList.size()); for (XxxDo o : xxxDoList) { XxxDo existed = xxxMapper.selectOne(new LambdaQueryWrapper () .eq(XxxDo::getId,o.getId())); if(null != existed){continue;} xxxMapper.insert(o); if(i==100){ int a = 1/0; } i++; } System.out.println("我的打印:循环插入结束"); } public List getData(){ .... return list; } }
日志:
_ _ |_ _ _|_. ___ _ | _ | | |\/|_)(_| | |_\ |_)||_|_\ / | 3.3.0 INFO 12-10-2023 07:39:41.014 main Started T1 in 13.452 seconds (JVM running for 17.662) INFO 12-10-2023 07:39:41.297 main {dataSource-1} inited INFO 12-10-2023 07:39:41.652 main Began transaction (1) for test context [DefaultTestContext@5a8c93 testClass = T1, testInstance = com.ali.cloud.test.T1@3bed3315, testMethod = t1@T1, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@119b0892 testClass = T1, locations = '{}', classes = '{class com.ali.cloud.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@1a3e8e24 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@20d525, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@69453e37, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4961f6af, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@f1c9823f, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@4c309d4d], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@4ed4a7e4]; rollback [false] 我的打印:插入数量 count: 2000 Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@63f6bed1] will be managed by Spring ==> Preparing: SELECT xxx from xxx where xxx ==> Parameters: 4444b1e53dxxx0d09bcaaa0c6362ayyy(String), 1234b1e53dxxx0d09bcaaa0c6362axxx(String), 0(Integer) <== Total: 0 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] from current transaction ==> Preparing: INSERT INTO xxx( xxx ) VALUES ( ?, ?, ?, ?, ?, ? ) ==> Parameters: 2342251622094285111(String),xxx, 2023-10-12 07:39:42.762(Timestamp), global_coding(String), 2023-10-12 07:39:42.762(Timestamp), global_coding(String) <== Updates: 1 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] from current transaction ==> Preparing: INSERT INTO xxx( xxx ) VALUES ( ?, ?, ?, ?, ?, ? ) ==> Parameters: 2342251622094285112(String),xxx, 2023-10-12 07:39:42.762(Timestamp), global_coding(String), 2023-10-12 07:39:42.762(Timestamp), global_coding(String) <== Updates: 1 我的打印:循环插入结束 Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] INFO 12-10-2023 07:40:10.436 main Committed transaction for test: [DefaultTestContext@5a8c93 testClass = T1, testInstance = com.ali.cloud.test.T1@3bed3315, testMethod = t1@T1, testException = java.lang.ArithmeticException: / by zero, mergedContextConfiguration = [MergedContextConfiguration@119b0892 testClass = T1, locations = '{}', classes = '{class com.ali.cloud.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@1a3e8e24 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@20d525, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@69453e37, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4961f6af, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@f1c9823f, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@4c309d4d], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]] INFO 12-10-2023 07:40:10.455 SpringContextShutdownHook {dataSource-1} closing ... INFO 12-10-2023 07:40:10.463 SpringContextShutdownHook {dataSource-1} closed
通过日志发现,默认用了事务transaction,这会有一个现象,就是在事务结束前,所有的insert是没有commit的。也就是必须得等到程序结束,数据库才会有数据存进去。
并且,还发现,如果中间出现异常,异常之前的数据是会提交到数据库。
实验:在程序跑起来,循环insert的时候,去查询数据库,是查不到这些数据的。
如果想要插入一条,数据库就有一条,只需要不使用事务即可。关闭事务的方式是:在方法上加上如下注解:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
即
@Test @Transactional(propagation = Propagation.NOT_SUPPORTED) public void t1() { int i = 0; ListxxxDoList = getData(); System.out.println("我的打印:插入数量 count:" + xxxDoList.size()); for (XxxDo o : xxxDoList) { XxxDo existed = xxxMapper.selectOne(new LambdaQueryWrapper () .eq(XxxDo::getId,o.getId())); if(null != existed){continue;} xxxMapper.insert(o); if(i==100){ int a = 1/0; } i++; } System.out.println("我的打印:循环插入结束"); }
日志如下:
_ _ |_ _ _|_. ___ _ | _ | | |\/|_)(_| | |_\ |_)||_|_\ / | 3.3.0 INFO 13-10-2023 09:37:55.641 main Started T1 in 13.353 seconds (JVM running for 16.686) 我的打印 count: 2293 Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@37348491] was not registered for synchronization because synchronization is not active INFO 13-10-2023 09:37:56.937 main {dataSource-1} inited JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring ==> Preparing: SELECT xxx from xxx where xxx ==> Parameters: 5555b1e53dxxx0d09bcaaa0c6362ayyy(String), 1234b1e53dxxx0d09bcaaa0c6362axxx(String), 0(Integer) <== Total: 0 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@37348491] Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@66bf40e5] was not registered for synchronization because synchronization is not active JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring ==> Preparing: INSERT INTO xxx( xxx ) VALUES ( ?, ?, ?, ?, ?, ? ) ==> Parameters: 2342251622094285111(String),xxx, 2023-10-12 07:39:42.762(Timestamp), global_coding(String), 2023-10-12 07:39:42.762(Timestamp), global_coding(String) <== Updates: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@66bf40e5] Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5a515e5d] was not registered for synchronization because synchronization is not active JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring ==> Preparing: SELECT xxx from xxx where xxx ==> Parameters: 5555b1e53dxxx0d09bcaaa0c6362ayyy(String), 1234b1e53dxxx0d09bcaaa0c6362axxx(String), 0(Integer) <== Total: 0 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5a515e5d] Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32f32623] was not registered for synchronization because synchronization is not active JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring ==> Preparing: INSERT INTO xxx( xxx ) VALUES ( ?, ?, ?, ?, ?, ? ) ==> Parameters: 2342251622094285111(String),xxx, 2023-10-12 07:39:42.762(Timestamp), global_coding(String), 2023-10-12 07:39:42.762(Timestamp), global_coding(String) <== Updates: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32f32623] 我的打印:循环插入结束 INFO 13-10-2023 09:38:00.505 SpringContextShutdownHook {dataSource-1} closing ... INFO 13-10-2023 09:38:00.512 SpringContextShutdownHook {dataSource-1} closed
根据两个日志对比,最明显的区别是开启事务的方法只创建了一个SqlSession,没开启事务的方法每一次执行sql都会创建一个SqlSession。
日志里是这句话:Creating a new SqlSession
若开启事务,处理SqlSession的步骤:释放SqlSession,再获取SqlSession,再去执行sql。
若关闭事务,处理SqlSession的步骤:关闭SqlSession,再创建SqlSession,再去执行sql。
当然,还有更具体的细节:
1. 开始都会先初始化数据源,最后都会关闭数据源。
日志:
{dataSource-1} inited,{dataSource-1} closing ...,{dataSource-1} closed
2. jdbc connection都用的是同一个,但两处日志不一样,一个是交给spring管理,一个是没交给spring管理。
日志:
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@63f6bed1] will be managed by Spring
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring
单独对某句sql做一个事务,即手动控制事务。
增加如下4行代码
DefaultTransactionDefinition dt = new DefaultTransactionDefinition(); dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); TransactionStatus status = platformTransactionManager.getTransaction(dt); platformTransactionManager.commit(status);
用法是:包裹住执行sql语句即可。
DefaultTransactionDefinition dt = new DefaultTransactionDefinition(); dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); TransactionStatus status = platformTransactionManager.getTransaction(dt); mapper.insert(o); platformTransactionManager.commit(status);
这是将查询和插入都包裹住的日志:
@Autowired private PlatformTransactionManager platformTransactionManager; @Test public void t1(){ for(int i=0; i _ _ |_ _ _|_. ___ _ | _ | | |\/|_)(_| | |_\ |_)||_|_\ / | 3.3.0 INFO 13-10-2023 17:53:24.989 main Started T1 in 12.882 seconds (JVM running for 16.576) INFO 13-10-2023 17:53:25.302 main {dataSource-1} inited INFO 13-10-2023 17:53:25.682 main Began transaction (1) for test context [DefaultTestContext@4ed4a7e4 testClass = T1, testInstance = com.ali.cloud.iot.T1@1c7350b0, testMethod = t1@T1, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@55651434 testClass = T1, locations = '{}', classes = '{class com.ali.cloud.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@3bc4ef12 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@587e5365, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@63475ace, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@291caca8, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@44ef74f7, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@38e79ae3], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@50448409]; rollback [false] 我的打印 count: 2293 Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32faa16c] JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@6ea246af] will be managed by Spring ==> Preparing: SELECT xxx ==> Parameters: xxx <== Total: 0 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32faa16c] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32faa16c] from current transaction ==> Preparing: INSERT INTO xxx ==> Parameters: xxx <== Updates: 1 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32faa16c] Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32faa16c] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32faa16c] Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32faa16c] Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e1ffe70] JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@6ea246af] will be managed by Spring ==> Preparing: SELECT xxx ==> Parameters: xxx <== Total: 0 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e1ffe70] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e1ffe70] from current transaction ==> Preparing: INSERT INTO xxx ==> Parameters: xxx <== Updates: 1 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e1ffe70] Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e1ffe70] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e1ffe70] Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e1ffe70] 我的打印:循环插入结束 INFO 13-10-2023 17:53:29.971 main Committed transaction for test: [DefaultTestContext@4ed4a7e4 testClass = T1, testInstance = com.ali.cloud.iot.T1@1c7350b0, testMethod = t1@T1, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@55651434 testClass = T1, locations = '{}', classes = '{class com.ali.cloud.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@3bc4ef12 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@587e5365, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@63475ace, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@291caca8, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@44ef74f7, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@38e79ae3], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]] INFO 13-10-2023 17:53:29.982 SpringContextShutdownHook {dataSource-1} closing ... INFO 13-10-2023 17:53:29.993 SpringContextShutdownHook {dataSource-1} closed这是查询在外面,单独包裹住插入的日志:
for(int i=0; i _ _ |_ _ _|_. ___ _ | _ | | |\/|_)(_| | |_\ |_)||_|_\ / | 3.3.0 INFO 13-10-2023 18:58:43.950 main Started T1 in 18.362 seconds (JVM running for 22.704) INFO 13-10-2023 18:58:44.356 main {dataSource-1} inited INFO 13-10-2023 18:58:45.206 main Began transaction (1) for test context [DefaultTestContext@1a3e8e24 testClass = T1, testInstance = com.ali.cloud.iot.T1@4ed4a7e4, testMethod = t1@T1, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@1c7350b0 testClass = T1, locations = '{}', classes = '{class com.ali.cloud.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@55651434 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@587e5365, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@63475ace, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@291caca8, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@44ef74f7, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@38e79ae3], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@3bc4ef12]; rollback [false] 我的打印:count: 2293 Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@29fe4840] will be managed by Spring ==> Preparing: SELECT xxxx ==> Parameters: xxx <== Total: 0 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] Transaction synchronization suspending SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b25ab31] JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@494c8f29] will be managed by Spring ==> Preparing: INSERT INTO xxx ==> Parameters: xxx <== Updates: 1 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b25ab31] Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b25ab31] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b25ab31] Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b25ab31] Transaction synchronization resuming SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] from current transaction ==> Preparing: SELECT xxx ==> Parameters: xxx <== Total: 0 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] Transaction synchronization suspending SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@574059d5] JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@494c8f29] will be managed by Spring ==> Preparing: INSERT INTO xxx ==> Parameters: xxx <== Updates: 1 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@574059d5] Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@574059d5] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@574059d5] Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@574059d5] Transaction synchronization resuming SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] 我的打印:循环插入结束 Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16da476c] INFO 13-10-2023 18:58:50.166 main Committed transaction for test: [DefaultTestContext@1a3e8e24 testClass = T1, testInstance = com.ali.cloud.iot.T1@4ed4a7e4, testMethod = t1@T1, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@1c7350b0 testClass = T1, locations = '{}', classes = '{class com.ali.cloud.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@55651434 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@587e5365, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@63475ace, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@291caca8, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@44ef74f7, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@38e79ae3], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]] INFO 13-10-2023 18:58:50.179 SpringContextShutdownHook {dataSource-1} closing ... INFO 13-10-2023 18:58:50.190 SpringContextShutdownHook {dataSource-1} closed根据日志,两种区别是:
第2种没有将查询包裹的,他是从事务中取出的session,fetched sqlsession from transaction,被包裹住的那个插入语句他是重新创建的session,creating a new sqlsession。
也就是说代码执行逻辑是这样:进入for循环->创建sqlsession1,执行查询sql,释放sqlsession1,挂起sqlsession1->进入到独立手动控制事务的代码->创建sqlsession2-,执行插入sql,释放、提交、注销、关闭sqlsession2,恢复sqlsession1->取出sqlsession1,执行查询sql,释放sqlsession1,挂起sqlsession1->...最后执行完了,走出for循环,执行其他代码,走出方法,提交、注销、关闭sqlsession1->关闭datasource
======================分割线==========================
文章到此已经结束,以下是紫薯布丁
@RunWith(SpringRunner.class)
@MybatisPlusTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Rollback(false)
public class T1 {
@Autowired
private XxxMapper xxxMapper;
@Test
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void t1() {
int i = 0;
List
xxxDoList = getData(); System.out.println("我的打印:插入数量 count:" + xxxDoList.size());
for (XxxDo o : xxxDoList) {
XxxDo existed = xxxMapper.selectOne(new LambdaQueryWrapper
() .eq(XxxDo::getId,o.getId()));
if(null != existed){continue;}
xxxMapper.insert(o);
if(i==100){
int a = 1/0;
}
i++;
}
System.out.println("我的打印:循环插入结束");
}
public List
getData(){ ....
return list;
}
}
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.3.0
INFO 12-10-2023 07:39:41.014 main Started T1 in 13.452 seconds (JVM running for 17.662)
INFO 12-10-2023 07:39:41.297 main {dataSource-1} inited
INFO 12-10-2023 07:39:41.652 main Began transaction (1) for test context [DefaultTestContext@5a8c93 testClass = T1, testInstance = com.ali.cloud.test.T1@3bed3315, testMethod = t1@T1, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@119b0892 testClass = T1, locations = '{}', classes = '{class com.ali.cloud.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@1a3e8e24 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@20d525, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@69453e37, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4961f6af, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@f1c9823f, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@4c309d4d], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@4ed4a7e4]; rollback [false]
我的打印:插入数量 count: 2000
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7]
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@63f6bed1] will be managed by Spring
==> Preparing: SELECT xxx from xxx where xxx
==> Parameters: 4444b1e53dxxx0d09bcaaa0c6362ayyy(String), 1234b1e53dxxx0d09bcaaa0c6362axxx(String), 0(Integer)
<== Total: 0
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] from current transaction
==> Preparing: INSERT INTO xxx( xxx ) VALUES ( ?, ?, ?, ?, ?, ? )
==> Parameters: 2342251622094285111(String),xxx, 2023-10-12 07:39:42.762(Timestamp), global_coding(String), 2023-10-12 07:39:42.762(Timestamp), global_coding(String)
<== Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7] from current transaction
==> Preparing: INSERT INTO xxx( xxx ) VALUES ( ?, ?, ?, ?, ?, ? )
==> Parameters: 2342251622094285112(String),xxx, 2023-10-12 07:39:42.762(Timestamp), global_coding(String), 2023-10-12 07:39:42.762(Timestamp), global_coding(String)
<== Updates: 1
我的打印:循环插入结束
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e62ead7]
INFO 12-10-2023 07:40:10.436 main Committed transaction for test: [DefaultTestContext@5a8c93 testClass = T1, testInstance = com.ali.cloud.test.T1@3bed3315, testMethod = t1@T1, testException = java.lang.ArithmeticException: / by zero, mergedContextConfiguration = [MergedContextConfiguration@119b0892 testClass = T1, locations = '{}', classes = '{class com.ali.cloud.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@1a3e8e24 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration, com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@20d525, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@69453e37, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4961f6af, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@f1c9823f, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@4c309d4d], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]
INFO 12-10-2023 07:40:10.455 SpringContextShutdownHook {dataSource-1} closing ...
INFO 12-10-2023 07:40:10.463 SpringContextShutdownHook {dataSource-1} closed
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.3.0
INFO 13-10-2023 09:37:55.641 main Started T1 in 13.353 seconds (JVM running for 16.686)
我的打印 count: 2293
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@37348491] was not registered for synchronization because synchronization is not active
INFO 13-10-2023 09:37:56.937 main {dataSource-1} inited
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring
==> Preparing: SELECT xxx from xxx where xxx
==> Parameters: 5555b1e53dxxx0d09bcaaa0c6362ayyy(String), 1234b1e53dxxx0d09bcaaa0c6362axxx(String), 0(Integer)
<== Total: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@37348491]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@66bf40e5] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring
==> Preparing: INSERT INTO xxx( xxx ) VALUES ( ?, ?, ?, ?, ?, ? )
==> Parameters: 2342251622094285111(String),xxx, 2023-10-12 07:39:42.762(Timestamp), global_coding(String), 2023-10-12 07:39:42.762(Timestamp), global_coding(String)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@66bf40e5]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5a515e5d] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring
==> Preparing: SELECT xxx from xxx where xxx
==> Parameters: 5555b1e53dxxx0d09bcaaa0c6362ayyy(String), 1234b1e53dxxx0d09bcaaa0c6362axxx(String), 0(Integer)
<== Total: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5a515e5d]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32f32623] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@259b85d6] will not be managed by Spring
==> Preparing: INSERT INTO xxx( xxx ) VALUES ( ?, ?, ?, ?, ?, ? )
==> Parameters: 2342251622094285111(String),xxx, 2023-10-12 07:39:42.762(Timestamp), global_coding(String), 2023-10-12 07:39:42.762(Timestamp), global_coding(String)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@32f32623]
我的打印:循环插入结束
INFO 13-10-2023 09:38:00.505 SpringContextShutdownHook {dataSource-1} closing ...
INFO 13-10-2023 09:38:00.512 SpringContextShutdownHook {dataSource-1} closed