springboot + mybatis的事务管理

结论: 

1. 不使用spring的事务管理,事务以每个mapper为单位,每个mapper调用完成后,就提交或回滚该mapper接口的结果。 

没有使用spring事务管理时, 每个mapper操作都会创建一个新的SqlSession(仅能被使用一次),  然后从DataSource中获取一条jdbc connection(可被多次使用,该连接不会被spring容器管理)来执行这个mapper接口。 一个mapper接口操作完成后jdbc connection放回DataSource, 然后提交或者回滚当前mapper接口的结果,最后关闭SqlSession. 所以一个方法中如果有多个查询的话, 可以考虑使用只读事务,防止多次创建SqlSession的开销

2. 使用spring事务管理时, 事务以方法为单位, 方法执行完成后, 整体提交或者回滚

使用spring事务管理时, 创建一个新的SqlSession(当前事务内均使用该SqlSession), 执行mapper时给该SQLSession注册当前事务锁, 然后从DataSource中获取一条jdbc connection(可被多次使用, 但该链接会被spring容器管理)来执行方法中的所有mapper接口, 每个mapper接口执行结束就释放这个事务性SQLSession。 等当前事务commiting(调用方法执行完)之后,会注销该SQLSession上的事务锁,然后关闭SqlSession, 提交或者回滚整个方法中涉及到的事务结果,最后jdbc connection被放回DataSource,

 

以上是再springboot2.1.6.RELEASE + mybatis项目中通过查看日志得到的结论, 可以将日志级别调整为debug查看。 

事务的提交主要体现在org.apache.ibatis.executor.statement.PreparedStatementHandler#update方法中的ps.execute(), 被spring管理事务时,该方法调用结束不会提交事务。 不被spring事务管理时, 该方法调用结束,就会提交事务

测试代码:

package com.carl.study.translation.mysqltranslation.service;

import com.carl.study.translation.mysqltranslation.mapper.UserMapper;
import com.carl.study.translation.mysqltranslation.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Random;

/**
 * @author changez
 * @desc
 * @datetime 2019-7-18 8:02
 */
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;


    // 不使用spring事务, 每个mapper都会创建一个新的SQLSession
    public void test1(){

        Random random = new Random();
        int rad  = random.nextInt(100);
        User user = new User();
        user.setName("n" + rad);
        user.setPassword(rad);
        User result = userMapper.selectByPrimaryKey(1);
        result = userMapper.selectByPrimaryKey(2);
    }

    // 使用spring事务, 多个mapper公用一个SQLSession, 没有写操作所以使用只读事务
    @Transactional(readOnly = true)
    public void readOnleTransactional(){

        Random random = new Random();
        int rad  = random.nextInt(100);
        User user = new User();
        user.setName("n" + rad);
        user.setPassword(rad);
        User result = userMapper.selectByPrimaryKey(1);
        result = userMapper.selectByPrimaryKey(2);
    }
}

 

日志输出(删除了部分无关日志记录):

不使用spring事务:

可以看到两处Creating a new SqlSession和Closing non transactional SqlSession

2019-07-19 06:59:01 DEBUG [http-nio-8080-exec-1] org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
2019-07-19 06:59:01 DEBUG [http-nio-8080-exec-1] org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7006f3e8] was not registered for synchronization because synchronization is not active
2019-07-19 06:59:01 DEBUG [http-nio-8080-exec-1] org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
2019-07-19 06:59:01 INFO [http-nio-8080-exec-1] com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
2019-07-19 06:59:04 DEBUG [http-nio-8080-exec-1] com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@2601281f
2019-07-19 06:59:04 INFO [http-nio-8080-exec-1] com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.

2019-07-19 06:59:04 DEBUG [http-nio-8080-exec-1] org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [HikariProxyConnection@407742333 wrapping com.mysql.cj.jdbc.ConnectionImpl@2601281f] will not be managed by Spring
2019-07-19 06:59:04 DEBUG [http-nio-8080-exec-1] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - ==>  Preparing: select * from t_user t where t.id=? 
2019-07-19 06:59:04 DEBUG [HikariPool-1 housekeeper] com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Pool stats (total=1, active=1, idle=0, waiting=0)
2019-07-19 06:59:04 DEBUG [HikariPool-1 connection adder] com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@2b97668b

2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - ==> Parameters: 1(Integer)
2019-07-19 06:59:05 DEBUG [HikariPool-1 connection adder] com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@e74ab39
2019-07-19 06:59:05 DEBUG [HikariPool-1 connection adder] com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - After adding stats (total=10, active=1, idle=9, waiting=0)
2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - <==      Total: 1
2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7006f3e8]

2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@62f9dc4a] was not registered for synchronization because synchronization is not active
2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [HikariProxyConnection@1465968045 wrapping com.mysql.cj.jdbc.ConnectionImpl@2601281f] will not be managed by Spring
2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - ==>  Preparing: select * from t_user t where t.id=? 
2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - ==> Parameters: 2(Integer)
2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - <==      Total: 1
2019-07-19 06:59:05 DEBUG [http-nio-8080-exec-1] org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@62f9dc4a]

使用spring事务:

可以看到仅有一处Creating a new SqlSession,且为该SQLSession注册事务锁, 一个mapper接口操作完成后,仅仅是释放了SQLSession上的事务锁,直到方法执行结束,才提交了jdbc connection上的事务

2019-07-19 07:03:04 DEBUG [http-nio-8080-exec-2] org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [com.carl.study.translation.mysqltranslation.service.UserService.readOnleTransactional]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2019-07-19 07:03:04 DEBUG [http-nio-8080-exec-2] org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [HikariProxyConnection@237305957 wrapping com.mysql.cj.jdbc.ConnectionImpl@2601281f] for JDBC transaction
2019-07-19 07:03:04 DEBUG [http-nio-8080-exec-2] org.springframework.jdbc.datasource.DataSourceUtils - Setting JDBC Connection [HikariProxyConnection@237305957 wrapping com.mysql.cj.jdbc.ConnectionImpl@2601281f] read-only
2019-07-19 07:03:04 DEBUG [http-nio-8080-exec-2] org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [HikariProxyConnection@237305957 wrapping com.mysql.cj.jdbc.ConnectionImpl@2601281f] to manual commit

2019-07-19 07:03:21 DEBUG [http-nio-8080-exec-2] org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
2019-07-19 07:03:21 DEBUG [http-nio-8080-exec-2] org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f6e455f]
2019-07-19 07:03:21 DEBUG [http-nio-8080-exec-2] org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [HikariProxyConnection@237305957 wrapping com.mysql.cj.jdbc.ConnectionImpl@2601281f] will be managed by Spring
2019-07-19 07:03:21 DEBUG [http-nio-8080-exec-2] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - ==>  Preparing: select * from t_user t where t.id=? 
2019-07-19 07:03:21 DEBUG [http-nio-8080-exec-2] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - ==> Parameters: 1(Integer)
2019-07-19 07:03:21 DEBUG [http-nio-8080-exec-2] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - <==      Total: 1
2019-07-19 07:03:21 DEBUG [http-nio-8080-exec-2] org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f6e455f]

2019-07-19 07:03:23 DEBUG [http-nio-8080-exec-2] org.mybatis.spring.SqlSessionUtils - Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f6e455f] from current transaction
2019-07-19 07:03:23 DEBUG [http-nio-8080-exec-2] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - ==>  Preparing: select * from t_user t where t.id=? 
2019-07-19 07:03:23 DEBUG [http-nio-8080-exec-2] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - ==> Parameters: 2(Integer)
2019-07-19 07:03:23 DEBUG [http-nio-8080-exec-2] com.carl.study.translation.mysqltranslation.mapper.UserMapper.selectByPrimaryKey - <==      Total: 1
2019-07-19 07:03:23 DEBUG [http-nio-8080-exec-2] org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f6e455f]

2019-07-19 07:03:37 DEBUG [http-nio-8080-exec-2] org.mybatis.spring.SqlSessionUtils - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f6e455f]
2019-07-19 07:03:37 DEBUG [http-nio-8080-exec-2] org.mybatis.spring.SqlSessionUtils - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f6e455f]
2019-07-19 07:03:37 DEBUG [http-nio-8080-exec-2] org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f6e455f]
2019-07-19 07:03:37 DEBUG [http-nio-8080-exec-2] org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction commit
2019-07-19 07:03:37 DEBUG [http-nio-8080-exec-2] org.springframework.jdbc.datasource.DataSourceTransactionManager - Committing JDBC transaction on Connection [HikariProxyConnection@237305957 wrapping com.mysql.cj.jdbc.ConnectionImpl@2601281f]
2019-07-19 07:03:37 DEBUG [http-nio-8080-exec-2] org.springframework.jdbc.datasource.DataSourceUtils - Resetting read-only flag of JDBC Connection [HikariProxyConnection@237305957 wrapping com.mysql.cj.jdbc.ConnectionImpl@2601281f]
2019-07-19 07:03:37 DEBUG [http-nio-8080-exec-2] org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [HikariProxyConnection@237305957 wrapping com.mysql.cj.jdbc.ConnectionImpl@2601281f] after transaction

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值