首页 > 其他分享 >Mybatis+SpringBoot集成+Plus+Generator

Mybatis+SpringBoot集成+Plus+Generator

时间:2023-03-13 10:12:54浏览次数:54  
标签:MyBatis Spring 接口 mybatis Plus https Mybatis SpringBoot

前言

1. 本文主要记录mybatis的使用及核心原理、mybatis集成springboot项目的相关内容、mybatis-plus概述和核心功能的使用。
2. 相关官网文档链接:(1)mybatis:https://mybatis.net.cn/index.html (2)mybatis-spring:https://mybatis.org/spring/zh/ (3)MyBatis-Spring-Boot-Starter:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/zh/index.html (4)mybatis-plus:https://baomidou.com/pages/24112f/

Mybatis概述

  • Mybatis是什么:MyBatis 是一款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

Mybatis入门

Mybatis配置说明

Mybatis映射文件

  • 官网说明:https://mybatis.net.cn/sqlmap-xml.html
  • 文件头
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="org.mybatis.example.BlogMapper">
        
    </mapper>
    
  • 映射规则:命名空间namespace + 方法名(id)
  • 映射标签select、insert、update、delete、sql、cache、cache-ref、resultMap
    • select – 映射查询语句。
    • insert – 映射插入语句;update 映射更新语句;delete – 映射删除语句;
    • resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素;
      • id & result:将一个列的值映射到一个简单数据类型(String, int, double, Date 等)的属性或字段(set注入)
        <!-- 
          column:数据库中的列名;
          property:映射到列结果的字段或属性;
          javaType:java类型,映射到的是HashMap,应该明确地指定javaType;
          jdbcType:JDBC类型;
          typeHandler:类型处理器
        -->
        <id column="bid" property="bid" javaType="Long" jdbcType="BIGINT"/>
        <result column="blog_name" property="blogName" jdbcType="String" javaType="VARCHAR"/>
        <result column="blog_desc" property="blogDesc" jdbcType="String" javaType="VARCHAR"/>
        
      • constructor:构造方法。将一个列的值映射到构造方法的参数中(构造器注入)
        <!--
          idArg & arg:传参
          column:数据库中的列名
          name:参数名
          其他与id&result一致
        -->
        <constructor>
          <idArg column="bid" javaType="int" name="bid" />
          <arg column="blog_name" javaType="String" name="blogName" />
          <arg column="blog_desc" javaType="_int" name="blogDesc" />
        </constructor>
        
      • association:关联,适用于一个对象中关联另一个对象的情况。
        <select id="selectAllOrder" resultMap="orderMap">
          SELECT * FROM OrderInfo oi,ShopInfo si WHERE oi.shop_id =si.shop_id
        </select>
        
        <resultMap id="orderMap" type="org.example.alan.Order">
            <id column="order_id" property="orderId"/>
            <result column="order_name" property="orderName"/>
            <result column="order_desc" property="orderDesc"/>
            <association property="shopInfo" resultMap="shopMap"/>
        </resultMap>
        
        <resultMap id="shopMap" type="org.example.alan.ShopInfo">
            <id column="shop_id" property="shopId"/>
            <result column="shop_name" property="shopName"/>
            <result column="shop_desc" property="shopDesc"/>
        </resultMap>
        
      • collection:集合,与association使用方法一致,适用于一个对象中关联另一个集合对象的情况。
      • discriminator:选择器,根据返回的结果选择映射不同的结果集
        <select id="selectAllShop" resultMap="shopMap02">
          SELECT shop_id,shop_name,shop_desc FROM ShopInfo si
        </select>
        
        <resultMap id="shopMap02" type="org.example.alan.ShopInfo">
            <id column="shop_id" property="shopId"/>
            <discriminator javaType="string" column="shop_id">
                <case value="10001">
                    <result column="shop_name" property="shopName"/>
                    <result column="shop_desc" property="shopDesc"/>
                </case>
                <case value="10002">
                    <result column="shop_name" property="shopDesc"/>
                    <result column="shop_desc" property="shopName"/>
                </case>
            </discriminator>
        </resultMap>
        
      • 自动映射:设置mapUnderscoreToCamelCase为true(数据库列使用大写字母组成的单词命名,单词间用下划线分隔;而 Java 属性一般遵循驼峰命名法约定)
    • sql – 可被其它语句引用的可重用语句块。
    • cache – 该命名空间的缓存配置、cache-ref – 引用其它命名空间的缓存配置;
      • 默认情况下,只启用了本地的会话缓存,仅对一个会话中的数据进行缓存。 通过配置<cache/>启用全局的二级缓存。mybatis一级和二级缓存均存在脏读问题,一般情况下不推荐使用
        <!--
          eviction:清除策略,默认LRU,可选LRU、FIFO、SOFT(软引用)、WEAK(弱引用)
          flushInterval:刷新间隔,默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新
          size:缓存空间,默认值是1024
          readOnly:只读,只读的缓存会给所有调用者返回缓存对象的相同实例,不能被修改
        -->
        <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
        
  • 传参
    • “#{}”用作“参数传递”(使用#{}参数语法时,MyBatis会创建PreparedStatement参数占位符,并通过占位符安全地设置参数,就像使用 ? 一样)。对于可能为NULL的列JDBC规定需要指定JDBC类型#{middleInitial,jdbcType=VARCHAR}
    • “${}”用作“字符串替换”。select * from ${blog} where bid = #{bid}(用这种方式接受用户的输入,并用作语句参数是不安全的,会导致潜在的 SQL 注入攻击)
    • 方法中的传参可用@Param("") 如Blog selectBlog(@Param("bid") long bid);

MyBatis 动态sql

  • 官网说明:https://mybatis.net.cn/dynamic-sql.html
  • 涉及标签if、choose (when, otherwise)、trim (where, set)、foreach
    • if:根据条件判断。
    • choose、when、otherwise:从多个条件选择一个。
    • where:在子元素返回时才插入WHERE语句,若子句的开头为 “AND” 或 “OR”,会将它们去除
    • set:在子元素返回时才插入SET语句,并会删掉额外的逗号
    • trim:与set元素等价(一般都用set吧?)
    • foreach:对集合进行遍历。
      • item:集合中元素迭代时的别名
      • index:在list和数组中,index是元素的序号,在map中,index是元素的key
      • open:foreach代码的开始符号,与close一起使用,常用在in(),values()
      • separator:元素之间的分隔符,如in(1,2)
      • close: foreach代码的关闭符号,与open一起使用,常用在in(),values()
      • collection: 要做foreach的对象,作为入参时,List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键。当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array将会失效。
        <!-- 批量条件 传参:List<Long> -->
        <select id="selectBlogAll" resultType="org.example.alan.Blog">
          select * from Blog where bid in
          <foreach collection="list" item="id" index="" open="(" separator="," close=")">
              #{id}
          </foreach>
        </select>
        <!-- 批量insert 传参:List<Blog> -->
        <insert id="insertAll">
          insert into Blog(bid,blog_name,blog_desc) values
          <foreach collection="list" item="blog" separator=",">
              (#{blog.bid},#{blog.blog_name},#{blog.blog_desc})
          </foreach>
        </insert>
        
      • script:在映射器接口类上使用动态SQL时使用。
      • bind:bind 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文(不是很懂,也没见用过)

Mybatis缓存

一级缓存

说明:本地缓存,SqlSession级别,默认开启

  1. 在同一个SqlSession中进行相同的 SQL 语句查询时,第二次以后的查询直接从缓存中获取;
  2. 在一次数据库会话中,执行修改、删除操作时,一级缓存会失效。等下次再查询sql语句时再加入到一级缓存中
  3. 会产生脏读情况。 如:当开启两个SqlSession去操作,一个sqlSession查询使一级缓存生效,另一个sqlSession执行修改操作,第一个sqlSession再去查询的时候查到的还是之前的数据。

二级缓存

说明:Mapper级别,配置<cache/>开启

  1. 开启后请求会先到二级缓存、再进行一级缓存、再到数据库
  2. 会产生脏读情况。 如:多表查询的情况(涉及多个namespace)(可通过cache-ref让多个namespace共用一个缓存,但一般不推荐)

Mybatis实现原理

  • Mybatis的实现原理是:JDK动态代理。Mybatis运行时通过JDK动态代理为每个Mapper接口生成代理对象MapperProxy(MapperProxyFactory#newInstance),代理对象会拦截接口方法(invoke),转而执行MappedStatement所代表的sql,然后将sql执行结果转化为Java对象返回(MapperMethod#execute、Statement#execute)

  • 主要类说明

    • SqlSessionFactoryBuilder:用来构建SqlSessionFactory,构建完成后即可丢弃

    • SqlSessionFactory:负责管理SqlSession生命周期,创建成功后一直存在

    • SqlSession:每次请求都会开启一次会话,请求结束时需要关闭会话。SqlSession包含操作SQL的所有方法。

    • DefaultSqlSessionFactory:SqlSessionFactory接口的具体实现类,包含Configuration对象

    • XMLConfigBuilder:负责解析mybatis配置文件

    • Configuration:包含Mybatis所有的配置内容(如:环境变量、映射器资源、设置、类型处理器等)

    • MapperRegistry:Mapper操作相关类,负责添加MapperProxyFactory对象,以及获取MapperProxy

    • MapperProxyFactory:Mapper代理工厂类,在加载配置时按资源类型缓存本地,负责创建MapperProxy

    • MapperProxy:Mapper接口的代理对象类,实现InvocationHandler,重写invoke方法。所有调用Mapper接口方法的请求都会转到这里执行

    • MapperMethod:Mapper代理对象方法处理类,负责向SqlSession发起请求并处理响应的结果

    • MappedStatement:Mapped.xml中SQL语句的声明对象

    • StatementHandler:SQL声明对象的处理类

    • Statement:SQL声明对象,负责调用数据库连接池中的SQL声明对象方法,请求数据库驱动连接数据库,执行静态SQL语句并返回它产生的结果。

  • 基础源码解析:可参考 https://cloud.tencent.com/developer/article/1772213

Mybatis搭配Spring

Spring项目使用Mybatis-Spring集成mybatis,升级为SpringBoot项目后可使用MyBatis-Spring-Boot-Starter进行集成

Mybatis-Spring

  • 官网说明:https://mybatis.org/spring/zh/index.html
  • 概述:MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
  • 关键类说明:
    • SqlSessionFactoryBean:代替SqlSessionFactoryBuilder,负责在spring中创建SqlSessionFactory
    • SqlSessionFactory:Spring在应用启动时创建。通常在 MyBatis-Spring 中,你不需要直接使用 SqlSessionFactoryBean 或对应的 SqlSessionFactory。 相反,session 的工厂 bean 将会被注入到 MapperFactoryBean 或其它继承于 SqlSessionDaoSupport 的 DAO(Data Access Object,数据访问对象)中。
    • SqlSession:bean 可以被注入一个线程安全的 SqlSession,它能基于 Spring 的事务配置来自动提交、回滚、关闭 session。
    • SqlSessionTemplate:MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSession。 SqlSessionTemplate 是线程安全的,可以被多个 DAO 或映射器所共享使用。

MyBatis-Spring-Boot-Starter

  • 概述:MyBatis-Spring-Boot-Starter可以帮助你更快地在SpringBoot之上构建MyBatis应用。你将通过使用这个模块实现以下目的:(1)构建单体应用程序;(2)将几乎不需要样板配置;(3)使用更少的XML配置。

  • 官网说明:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/zh/index.html

  • 使用MyBatis-Spring-Boot-Starter的好处

    1. 自动探测存在的DataSource
    2. 将使用 SqlSessionFactoryBean 创建并注册一个 SqlSessionFactory 的实例,并将探测到的 DataSource 作为数据源
    3. 将创建并注册一个从 SqlSessionFactory 中得到的 SqlSessionTemplate 的实例
    4. 自动扫描你的 mapper,将它们与 SqlSessionTemplate 相关联,并将它们注册到Spring 的环境(context)中去,这样它们就可以被注入到你的bean中
  • MyBatis-Spring-Boot-Starter安装和入门使用

    <!--引入依赖jar包即可-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>3.0.1</version>
    </dependency>
    
    // Mapper接口
    @Mapper
    public interface CityMapper {
      @Select("SELECT * FROM CITY WHERE state = #{state}")
      City findByState(@Param("state") String state);
    }
    
    @SpringBootApplication
    public class SampleMybatisApplication implements CommandLineRunner {
      //依赖注入Mapper接口 Bean
      private final CityMapper cityMapper;
      public SampleMybatisApplication(CityMapper cityMapper) {
        this.cityMapper = cityMapper;
      }
      //Mapper接口的使用
      @Override
      public void run(String... args) throws Exception {
        System.out.println(this.cityMapper.findByState("CA"));
      }
      public static void main(String[] args) {
        SpringApplication.run(SampleMybatisApplication.class, args);
      }
    }
    
  • 发现mapper的方式

    1. 默认自动搜寻带有 @Mapper 注解的 mapper 接口
    2. 使用@MapperScan,指定一个自定义的注解或接口来扫描mapper接口 @MapperScan("org.mybatis.spring.sample.mapper")
    3. xml配置方式:https://mybatis.org/spring/zh/mappers.html#scan
  • SpringBoot中Mybatis的相关配置

    • configuration配置项:参考 https://mybatis.org/mybatis-3/zh/configuration.html#settings
    • mybatis通用配置项
      mybatis:
        # XML 映射文件的路径
        mapper-locations:
          - classpath:mapper/*.xml
        # 设置
        configuration:
          # 是否开启驼峰命名自动映射
          map-underscore-to-camel-case: true
          # 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存
          cache-enabled: false
          # 本地缓存机制 SESSION缓存一个会话中执行的所有查询 STATEMENT本地缓存将仅用于执行语句
          local-cache-scope: STATEMENT
          # 指定 MyBatis 所用日志的具体实现,未指定时将自动查找
          log-impl: SLF4J
      

Mybatis-Plus

概述

  • 是什么:MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
  • 特性:无侵入、损耗小、强大的 CRUD 操作、支持Lambda形式调用 等
  • 支持的数据库:MySQL,Oracle,DB2,H2、PostgreSQL等
  • 框架结构

快速入门

代码生成器(新)

Entity类注解说明

  • @TableName:表名注解,标识实体类对应的表
  • @TableId:主键注解(value:主键字段名;type:指定主键类型,默认IdType.NONE)
    • IdType说明
      • 可选值:AUTO-自增、NONE-无状态、INPUT-自动生成、ASSIGN_ID-自定义ID、ASSIGN_UUID-自定义ID
      • AUTO:按照数据库中主键设定的自增规则进行自增;
      • NONE:无任何操作
      • INPUT:使用内置“主键策略”生成主键id,需要注入IKeyGenerator接口配合使用。https://baomidou.com/pages/e131bd/
      • ASSIGN_ID:使用“自定义ID生成器”生成主键id,默认使用“雪花算法”,需要注入IdentifierGenerator接口并实现其nextId方法。https://baomidou.com/pages/568eb2/
      • ASSIGN_UUID:使用“自定义ID生成器”生成主键id,默认使用“雪花算法+UUID(不含中划线)”,需要注入IdentifierGenerator接口并实现其nextUUID方法
    • 示例
      //1. 定义Entity类
      @TableName("TEST_TABLE")
      public class TestEntity {
        //2. 定义主键,并设置主键生成类型,当设置类型为INPUT、ASSIGN_ID、ASSIGN_UUID时,需要注入对应接口
        @TableId(value = "test_id", type = IdType.AUTO)
        private String testId;
      }
      //3. 类型为INPUT
      @Bean
      public IKeyGenerator keyGenerator() {
        return new H2KeyGenerator();
      }
      //3. 类型为ASSIGN_ID
      @Component
      public class CustomIdGenerator implements IdentifierGenerator {
        private final AtomicLong al = new AtomicLong(1);
        @Override
        public Number nextId(Object entity) {
          //可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.
          String bizKey = entity.getClass().getName();
          log.info("bizKey:{}", bizKey);
          MetaObject metaObject = SystemMetaObject.forObject(entity);
          String name = (String) metaObject.getValue("name");
          final long id = al.getAndAdd(1);
          log.info("为{}生成主键值->:{}", name, id);
          return id;
        }
      }
      
  • @TableField:字段注解(非主键)
  • @Version:乐观锁注解、标记 @Version 在字段上
  • @EnumValue:描述:普通枚举类注解(注解在枚举字段上)
  • @TableLogic:表字段逻辑处理注解(逻辑删除)
  • @KeySequence:序列主键策略 oracle(value:序列名;dbType:数据库类型,未配置默认使用注入 IKeyGenerator 实现,多个实现必须指定。默认DbType.OTHER)
  • @InterceptorIgnore:value值为 1 | yes | on 视为忽略。@InterceptorIgnore(tenantLine = "1")
  • @SqlParser:不知道有啥用
  • @OrderBy:内置 SQL 默认指定排序,优先级低于 wrapper 条件查询(isDesc:是否倒序查询,默认true;sort:数字越小越靠前,默认Short.MAX_VALUE)

CRUD 接口

  • Service CRUD接口

    • 通用 Service CRUD 封装IService接口。如需自定义通用Service方法,请创建自己的IBaseService继承IService
    • CRUD方法:save/saveBatch/saveOrUpdate/saveOrUpdateBatch、remove/removeBatchByIds/removeById/removeByIds、update/updateBatchById/updateById、getById/getEntityClass/getObj/getOne/、list/listByIds/listObjs、page/pageMaps、count
      //基类
      public interface IBaseService<T> extends IService<T> {
      
      }
      //定义接口
      public interface IShopService extends IBaseService {
      
      }
      
    • 详情参考:https://baomidou.com/pages/49cc81/#service-crud-接口
  • Mapper CRUD接口

    • 通用 CRUD 封装BaseMapper接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器
    • CRUD方法:insert、delete/deleteById/deleteBatchIds、update/updateById、selectById/selectBatchIds/selectCount/selectList/selectPage/selectOne
      public interface BlogMapper<T> extends BaseMapper<T> {
      
      }
      
    • 详情参考:https://baomidou.com/pages/49cc81/#mapper-crud-接口
  • 分页查询

    • 使用方式
      1. 引入插件主体MybatisPlusInterceptor和分页插件PaginationInnerInterceptor
      2. 请求查询传入IPage参数即可
    • 示例
      //1. 引入插件
      @Configuration
      @MapperScan("org.example.mapper")
      public class MybatisPlusConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            return interceptor;
        }
      }
      
      //2. 调用内置page方法查询
      @Override
      public List<Person> selectPersonPage(SelectPersonReqBo reqBo) {
        Page page = new Page<>(reqBo.getNum(), reqBo.getSize());
        LambdaQueryWrapper<Person> wrapper = new LambdaQueryWrapper<Person>().eq(Person::getPersonSex, reqBo.getPersonSex());
        return this.page(page, wrapper).getRecords();
      }
      
      //2. 执行自定义SQL查询
      //2.1 service
      @Override
      public List<Person> selectPersonPage(SelectPersonReqBo reqBo) {
        return personMapper.pageSelectPerson(new Page<>(reqBo.getNum(), reqBo.getSize()),reqBo.getPersonSex());
      }
      //2.2 mapper
      List<Person> pageSelectPerson(IPage<Person> page, @Param("personSex") String personSex);
      //2.3 mapper.xml
      <select id="pageSelectPerson" resultType="org.example.entity.Person">
        SELECT p.person_id ,p.person_name ,p.person_desc,p.person_sex FROM Person p
        <where>
            <if test="personSex != null and personSex != '' ">
                p.person_sex = #{personSex}
            </if>
        </where>
      </select>
      
    • 官网说明:https://baomidou.com/pages/97710a/

条件构造器

  • AbstractWrapper
    • 概述:AbstractWrapper是QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类。用于生成 sql 的 where 条件, 包含几乎所有sql操作的相关方法,同时entity 属性也用于生成 sql 的 where 条件。
    • 方法:allEq/eq/ne、gt/ge/lt/le、between/notBetween、like/likeLeft/likeRight/notLike/notLikeLeft/notLikeRight、isNull/isNotNull、in/notIn/inSql/notInSql、groupBy、orderByAsc/orderByDesc/orderBy、having、func、or/and、nested/apply/last、exists/notExists
    • 官网说明:https://baomidou.com/pages/10c804/#abstractwrapper
  • QueryWrapper
  • UpdateWrapper

SimpleQuery 工具类

标签:MyBatis,Spring,接口,mybatis,Plus,https,Mybatis,SpringBoot
From: https://www.cnblogs.com/alan1995/p/17188971.html

相关文章