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;

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

通过日志发现,默认用了事务transaction,这会有一个现象,就是在事务结束前,所有的insert是没有commit的。也就是必须得等到程序结束,数据库才会有数据存进去。

并且,还发现,如果中间出现异常,异常之前的数据是会提交到数据库。

实验:在程序跑起来,循环insert的时候,去查询数据库,是查不到这些数据的。

关闭事务

如果想要插入一条,数据库就有一条,只需要不使用事务即可。关闭事务的方式是:在方法上加上如下注解:

@Transactional(propagation = Propagation.NOT_SUPPORTED)

@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("我的打印:循环插入结束");

}

 日志如下:

_ _ |_ _ _|_. ___ _ | _

| | |\/|_)(_| | |_\ |_)||_|_\

/ |

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

DefaultTransactionDefinition dt = new DefaultTransactionDefinition();

dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);

TransactionStatus status = platformTransactionManager.getTransaction(dt);

mapper.select(o);

mapper.insert(o);

platformTransactionManager.commit(status);

}

}

_ _ |_ _ _|_. ___ _ | _

| | |\/|_)(_| | |_\ |_)||_|_\

/ |

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

mapper.select(o);

DefaultTransactionDefinition dt = new DefaultTransactionDefinition();

dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);

TransactionStatus status = platformTransactionManager.getTransaction(dt);

mapper.insert(o);

platformTransactionManager.commit(status);

}

_ _ |_ _ _|_. ___ _ | _

| | |\/|_)(_| | |_\ |_)||_|_\

/ |

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

好文链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: