Mybatis笔记

官网链接

英文官网:https://mybatis.org/mybatis-3/

中文官网:https://mybatis.net.cn/

Mybatis中自动生成主键

<insert id="" parameterType="" keyColumn="id" keyProperty="id" useGeneratedKeys="true">
  • useGeneratedKeys=true表示使用数据库自动增长的主键

  • keyProperty设置自增主键返回字段(用户在插入数据之后获取相应主键)

  • keyColumn用于指定数据库table中的主键

这是三个属性同时使用时,则可以使用数据库中自增长的主键,并且可以将主键的值返回给keyProperty中写好的字段

Mybatis批处理

public class MybatisBatchUtils {
    
    /**
    * 每次处理1000条
    */
    private static final int BATCH_SIZE = 1000;
    
    @Resource
    private SqlSessionFactory sqlSessionFactory;
    
    /**
    * 批量处理修改或者插入
    *
    * @param data     需要被处理的数据
    * @param mapperClass  Mybatis的Mapper类
    * @param function 自定义处理逻辑 (函数式接口)
    * @return int 影响的总行数
    */
    public <T,U,R>int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> function)
    {
        int i = 1;
        SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            U mapper = batchSqlSession.getMapper(mapperClass);
            int size = data.size();
            for (T element : data) {
                // 更新:mapper.update(element);
                // 插入:mapper.insert(element)
                function.apply(element,mapper);
                if ((i % BATCH_SIZE == 0) || i == size) {
                    batchSqlSession.flushStatements();
                }
                i++;
            }
            // 非事务环境下强制commit,事务情况下该commit相当于无效
            batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
        } catch (Exception e) {
            batchSqlSession.rollback();
            throw new CustomException(e);
        } finally {
            batchSqlSession.close();
        }
        return i - 1;
    }
} 

使用案例:batchUtils.batchUpdateOrInsert(数据集合, xxxxx.class, (item, mapper实例对象) -> mapper实例对象.insert方法(item)); 函数式接口可以用Lambda的方式实现具体逻辑

如果方法上用了@Transactional注解,由于在 Spring 集成的情况下,事务连接由 Spring 管理(SpringManagedTransaction),所以这里不需要手动关闭 sqlSession,在这里手动提交(commit)或者回滚(rollback)也是无效的。如果没有使用事务注解,那就一步一步来,提交了再关闭。

PreparedStatement 预编译

  1. 预编译显式开启(在url中指定useServerPrepStmts=true),否则PreparedStatement不会向mysql发送预编译(Prepare命令)的请求;
  2. 每次向mysql发送预编译请求,不管之前有没有执行过此SQL语句,只要请求的命令是Prepare或Query,mysql就会重新编译一次SQL语句,并返回此链接当前唯一的Statement ID,后续执行SQL语句的时候,程序只需拿着Statement ID和参数就可以了;
  3. 当预编译的SQL语句有语法错误,则mysql的响应会携带错误信息,但此错误信息JDBC感知不到(或者说mysql-connetor-java.jar包里的实现将其忽略掉了),此时还会继续往下执行代码,当执行到executeXxx()方法时,由于没有Statement ID(所以就会将拼接完整的SQL语句值已经将占位符(?)替换掉再次发给mysql请求执行,此时mysql响应有语法错误,这时JDBC就会抛出语法错误异常),所以检查语法那一步实在mysql-server中做的(通过抓包可以看到);
  4. PreparedStatement对性能的提高是利用缓存实现的,需要显式开启(在url中指定cachePrepStmts=true),此缓存是mysql-connetor-java.jar包里实现的(非mysql-server中的缓存),缓存的key是完整的sql语句,value是PreparedStatement对象。放入缓存是PreparedStatement.close()触发的,所以只要缓存PreparedStatement对象没有关闭,你不管调用多少次connection.prapareStatement(sql)对相同的sql语句进行预编译,都会将预编译的请求发给mysql,mysql也会对每一个sql语句不管是否相同进行预编译,并生成一个唯一的Statement ID并返回;
  5. 缓存是针对链接的,每个链接都是独立的,不共享缓存 。

where标签

https://blog.youkuaiyun.com/wo541075754/article/details/123244510

这里就涉及到where标签的两个特性:

  • 第一,只有if标签有内容的情况下才会插入where子句;
  • 第二,若子句的开通为 “AND” 或 “OR”,where标签会将它替换去除;

但需要注意的是:where标签只会 智能的去除(忽略)首个满足条件语句的前缀。所以建议在使用where标签时,每个语句都最好写上 and 前缀或者 or 前缀。

trim标签

https://zhuanlan.zhihu.com/p/425922768

基本格式:

<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=""></trim>
  • prefix:

    • 表示在trim包裹的SQL语句前面添加的指定内容。
  • suffix:

    • 表示在trim包裹的SQL末尾添加指定内容
  • prefixOverrides:

    • 表示去掉(覆盖)trim包裹的SQL的指定首部内容
  • suffixOverrides:

    • 表示去掉(覆盖)trim包裹的SQL的指定尾部内容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值