mybatis-plus 学习笔记

一、简介

MyBatis-Plus 官网

二、简单使用

本文的开发环境:

  • IDE:IDEA 2021.3
  • JDK:JDK 11
  • Maven:Maven 3.8.4
  • SpringBoot:SpringBoot 2.7.0
  • MySQL:MySQL 8.0

1、引入依赖

<dependencies>
	 
     <dependency>
         <groupId>com.baomidougroupId>
         <artifactId>mybatis-plus-boot-starterartifactId>
         <version>3.5.1version>
     dependency>
	
	 
     <dependency>
         <groupId>mysqlgroupId>
         <artifactId>mysql-connector-javaartifactId>
         <version>8.0.21version>
         <scope>runtimescope>
     dependency>

	
	<dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
 dependencies>

2、填写配置文件

application.yaml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志功能

3、编写与表对应的实体类

@Data //lombok提供的注解,自动生成 get、set、toString等方法
public class User {

    private Integer id;
    private String name;
    private Integer age;
    private String email;
}

4、编写 Mapper 接口

@Mapper
public interface UserMapper extends BaseMapper<User> {
	// BaseMapper已经提供了基础的CRUD方法
}

5、测试

@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelect(){
        User user = userMapper.selectById(1);
        System.out.println(user);
    }
}

三、BaseMapper

BaseMapper:MyBatis-Plus 提供的一个通用 CRUD 接口。

1、常用方法

  • // 插入一条记录
    int insert(T entity);
    
  • // 根据 entity 条件,删除记录
    int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
    // 删除(根据ID 批量删除)
    int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
    // 根据 ID 删除
    int deleteById(Serializable id);
    // 根据 columnMap 条件,删除记录
    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
    
  • // 根据 whereWrapper 条件,更新记录
    int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
    // 根据 ID 修改
    int updateById(@Param(Constants.ENTITY) T entity);
    
  • // 根据 ID 查询
    T selectById(Serializable id);
    // 根据 entity 条件,查询一条记录
    T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    
    // 查询(根据ID 批量查询)
    List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
    // 根据 entity 条件,查询全部记录
    List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 查询(根据 columnMap 条件)
    List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
    // 根据 Wrapper 条件,查询全部记录
    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    
    // 根据 entity 条件,查询全部记录(并翻页)
    IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据 Wrapper 条件,查询全部记录(并翻页)
    IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据 Wrapper 条件,查询总记录数
    Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    

四、IService

IService:MyBatis-Plus 提供的一个通用业务接口,同时还提供了其实现类 ServiceImpl。

1、简单使用

  • 编写自定义 Service 接口
    public interface UserService extends IService<User> {
    	// IService接口中定义了许多CRUD方法
    }
    
  • 实现自定义 Service 接口
    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
    	// ServiceImpl实现类已经实现了IService接口中定义的方法
    }
    
  • 测试
    @SpringBootTest
    public class ServiceTest {
    
        @Autowired
        private UserService userService;
    
        @Test
        public void testSave(){
            User user = new User();
            user.setName("张三");
            user.setAge(22);
            user.setEmail("[email protected]");
            userService.save(user);
        }
    }
    

2、常用方法

  • // 插入一条记录(选择字段,策略插入)
    boolean save(T entity);
    // 插入(批量)
    boolean saveBatch(Collection<T> entityList);
    // 插入(批量)
    boolean saveBatch(Collection<T> entityList, int batchSize);
    
    // TableId 注解存在更新记录,否插入一条记录
    boolean saveOrUpdate(T entity);
    // 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
    boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
    // 批量修改插入
    boolean saveOrUpdateBatch(Collection<T> entityList);
    // 批量修改插入
    boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
    
  • // 根据 entity 条件,删除记录
    boolean remove(Wrapper<T> queryWrapper);
    // 根据 ID 删除
    boolean removeById(Serializable id);
    // 根据 columnMap 条件,删除记录
    boolean removeByMap(Map<String, Object> columnMap);
    // 删除(根据ID 批量删除)
    boolean removeByIds(Collection<? extends Serializable> idList);
    
  • // 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
    boolean update(Wrapper<T> updateWrapper);
    // 根据 whereWrapper 条件,更新记录
    boolean update(T updateEntity, Wrapper<T> whereWrapper);
    // 根据 ID 选择修改
    boolean updateById(T entity);
    // 根据ID 批量更新
    boolean updateBatchById(Collection<T> entityList);
    // 根据ID 批量更新
    boolean updateBatchById(Collection<T> entityList, int batchSize);
    
  • // 根据 ID 查询
    T getById(Serializable id);
    // 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
    T getOne(Wrapper<T> queryWrapper);
    // 根据 Wrapper,查询一条记录
    T getOne(Wrapper<T> queryWrapper, boolean throwEx);
    // 根据 Wrapper,查询一条记录
    Map<String, Object> getMap(Wrapper<T> queryWrapper);
    // 根据 Wrapper,查询一条记录
    <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
    
    // 查询所有
    List<T> list();
    // 查询列表
    List<T> list(Wrapper<T> queryWrapper);
    // 查询(根据ID 批量查询)
    Collection<T> listByIds(Collection<? extends Serializable> idList);
    // 查询(根据 columnMap 条件)
    Collection<T> listByMap(Map<String, Object> columnMap);
    // 查询所有列表
    List<Map<String, Object>> listMaps();
    // 查询列表
    List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
    // 查询全部记录
    List<Object> listObjs();
    // 查询全部记录
    <V> List<V> listObjs(Function<? super Object, V> mapper);
    // 根据 Wrapper 条件,查询全部记录
    List<Object> listObjs(Wrapper<T> queryWrapper);
    // 根据 Wrapper 条件,查询全部记录
    <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
    
    // 查询总记录数
    int count();
    // 根据 Wrapper 条件,查询总记录数
    int count(Wrapper<T> queryWrapper);
    
  • 分页
    // 根据 ID 查询
    T getById(Serializable id);
    // 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
    T getOne(Wrapper<T> queryWrapper);
    // 根据 Wrapper,查询一条记录
    T getOne(Wrapper<T> queryWrapper, boolean throwEx);
    // 根据 Wrapper,查询一条记录
    Map<String, Object> getMap(Wrapper<T> queryWrapper);
    // 根据 Wrapper,查询一条记录
    <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
    

五、常用注解

1、@TableName

@TableName:指定 java 实体类对应的表名。如果不指定,默认表名是当前类名首字母小写。

@TableName("user")
@Data
public class User {

    private Integer id;
    private String name;
    private Integer age;
    private String email;
}

2、@TableId

2.1 主键id映射

MyBatisPlus 在进行实体类与表的映射时,默认寻找属性名和字段名都是id的属性和字段作为主键id。当属性名或字段名不是id时,就需要@TableId注解了。

  • 示例1:假设表中的主键名是uid,且当前实体类的属性名也是uid
    public class User {
    
    	@TableId //把 uid属性与表中的 uid字段对应
        private Integer uid;
        private String name;
    }
    
  • 示例2:假设表中的主键名是id,但当前实体类的属性名是uid
    public class User {
    	
    	@TableId("id") //把 uid属性与表中的 id字段对应
    	//@TableId(value = "id")
        private Integer uid;
        private String name;
    }
    
2.2 主键策略

MyBatisPlus 默认的主键策略是IdType.ASSIGN_ID(基于雪花算法的策略生成数据id,与数据库id是否设置自增无关)。若要修改主键策略,可使用@TableId注解的type属性。

public class User {

    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
}

可在配置文件中设置全局主键策略:

mybatis-plus:
  global-config:
    db-config:
      table-prefix: t_ # 设置全局实体类对应表的前缀
      id-type: auto # 设置全局主键策略

3、@TbaleField

@TbaleField:设置实体类的属性对应表中的哪个字段。

  • 示例:假设属性名为 userName,表中的字段名为 name。
    public class User {
    
        private Integer id;
    
        @TableField("name")
        private String userName;
    }
    

4、@TableLogic

@TableLogic:把实体类的当前属性作为逻辑删除的标志位。
逻辑删除:实际执行的是 update 操作,只是修改标志位的值。

user表
mybatis-plus 学习笔记_第1张图片
User类

@Data
public class User {

    private Integer id;
    private String name;
    private Integer age;
    private String email;

    @TableLogic
    private Integer isDeleted;
}

逻辑删除测试

@Test
    public void testLogicDelete(){
        userMapper.deleteById(1); 
        // 实际执行的SQL语句:
        // UPDATE user SET is_deleted=1 WHERE id=? AND is_deleted=0
        
        User user = userMapper.selectById(1); 
        // 实际执行的SQL语句:
        // SELECT id,name,age,email,is_deleted FROM user WHERE id=? AND is_deleted=0
        
        System.out.println(user); //null
    }

六、条件构造器 - Wrapper

Wrapper:最顶级的条件构造抽象类。
QueryWrapper:用于封装查询条件。
UpdateWrapper:用于封装 update 条件。
LambdaQueryWrapper:使用 Lambda 语法。

1、QueryWrapper 使用

  • 组装查询条件
    @Test
    public void testQueryWrapper(){
        //查询用户名包含"a",年龄在20到30之间,邮箱不为null的用户信息,查询结果按年龄降序排序
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name","a")
                    .between("age",20,30)
                    .isNotNull("email")
                    .orderByDesc("age");
        List<User> users = userMapper.selectList(queryWrapper);
        //实际执行的SQL语句:
        //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL) ORDER BY age DESC
        users.forEach(System.out::println);
    }
    
  • 组装删除条件
    @Test
       public void testQueryWrapper2(){
           //删除年龄在25到30之间的用户
           QueryWrapper<User> queryWrapper = new QueryWrapper<>();
           queryWrapper.between("age",25,30);
           //实际执行的SQL语句:
           //UPDATE user SET is_deleted=1 WHERE is_deleted=0 AND (age BETWEEN ? AND ?)
           userMapper.delete(queryWrapper);
       }
    
  • 组装修改条件
    @Test
    public void testQueryWrapper3(){
        //把名字中包含"a"且年龄在20到30之间的用户的邮箱设为"[email protected]"
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name","a")
                    .between("age",20,30);
    
        User user = new User();
        user.setEmail("[email protected]");
        userMapper.update(user, queryWrapper);
        //实际执行SQL语句:
        //UPDATE user SET email=? WHERE is_deleted=0 AND (name LIKE ? AND age BETWEEN ? AND ?)
    }
    

2、UpdateWrapper 使用

@Test
public void testUpdateWrapper(){
    //把名字中包含"a"且年龄在20到30之间的用户的邮箱设为"[email protected]"
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.like("name","a")
                 .between("age","20","30")
                 .set("email","[email protected]");
    userMapper.update(null,updateWrapper);
    //实际执行SQL语句:
    //UPDATE user SET email=? WHERE is_deleted=0 AND (name LIKE ? AND age BETWEEN ? AND ?)
}

3、条件优先级

@Test
public void test(){
    //查询 id在1到3之间 且(名字中包含"a" 或 年龄大于20) 的用户信息
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.between("id",1,3)
                .and(queryWrapper1 -> queryWrapper1.like("name","a").or().gt("age",20));
    List<User> users = userMapper.selectList(queryWrapper);
    //实际执行SQL语句:
    //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (id BETWEEN ? AND ? AND (name LIKE ? OR age > ?))
    users.forEach(System.out::println);
}

4、设置查询字段

@Test
public void testSelect(){
    //查询所有用户的名字、年龄和邮箱信息
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("name","age","email");
    List<User> users = userMapper.selectList(queryWrapper);
    //实际执行SQL语句:
    //SELECT name,age,email FROM user WHERE is_deleted=0
    users.forEach(System.out::println);
}

5、实现子查询

@Test
public void testSubSelect(){
    //查询id小于3的用户信息
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.inSql("id","select id from user where id < 3");
    List<User> users = userMapper.selectList(queryWrapper);
    //实际执行SQL语句:
    //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (id IN (select id from user where id < 3))
    users.forEach(System.out::println);
}

6、使用 condition 组装条件

@Test
public void testCondition(){
    //假设查询条件是从浏览器拿到的,需要先判断是否为空
    String name = "a";
    Integer ageBegin = null;
    Integer ageEnd = 30;

    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //在每个查询条件之前加个判断
    queryWrapper.like(StringUtils.isNotBlank(name),"name","a")
                .ge(ageBegin != null,"age",ageBegin)
                .le(ageEnd != null,"age",ageEnd);

    List<User> users = userMapper.selectList(queryWrapper);
    //实际执行SQL语句:
    //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (name LIKE ? AND age <= ?)
    users.forEach(System.out::println);
}

7、LambdaQueryWrapper

LambdaQueryWrapper 与 QueryWrapper功能一致,只是为了防止填写参数时写错字段名,采用函数式接口的方式编写。

@Test
public void testLambdaQueryWrapper(){
    //假设查询条件是从浏览器拿到的,需要先判断是否为空
    String name = "a";
    Integer ageBegin = null;
    Integer ageEnd = 30;

    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.like(StringUtils.isNotBlank(name),User::getName,"a")
                .ge(ageBegin != null,User::getAge,ageBegin)
                .le(ageEnd != null,User::getAge,ageEnd);

    List<User> users = userMapper.selectList(queryWrapper);
    //实际执行SQL语句:
    //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (name LIKE ? AND age <= ?)
    users.forEach(System.out::println);
}

8、LambdaUpdateWrapper

LambdaUpdateWrapper 与 UpdateWrapper功能一致,只是为了防止填写参数时写错字段名,采用函数式接口的方式编写。

@Test
public void testLambdaUpdateWrapper(){
    //把名字中包含"a"且年龄在20到30之间的用户的邮箱设为"[email protected]"
    LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
    updateWrapper.like(User::getName,"a")
            .between(User::getAge,"20","30")
            .set(User::getEmail,"[email protected]");
    userMapper.update(null,updateWrapper);
    //实际执行SQL语句:
    //UPDATE user SET email=? WHERE is_deleted=0 AND (name LIKE ? AND age BETWEEN ? AND ?)
}

七、常用插件

1、分页插件

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能。

简单使用:

  1. 编写配置类:
    @Configuration
    public class MyBatisPlusConfig {
    
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            //添加分页插件
            mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            return mybatisPlusInterceptor;
        }
    }
    
  2. 测试:
    @Test
    public void testPage(){
         Page<User> page = new Page<>(2,2);
         userMapper.selectPage(page,null);
         //实际执行SQL语句:
         //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 LIMIT ?,?
         System.out.println("当前页数:" + page.getCurrent());
         System.out.println("每页记录数:" + page.getSize());
         System.out.println("总页数:" + page.getPages());
         System.out.println("总记录数:" + page.getTotal());
         System.out.println("当前页数据:" + page.getRecords());
     }
    

自定义分页方法:

  1. UserMapper接口中定义一个方法:
    @Mapper
    public interface UserMapper extends BaseMapper<User> {
    
        /**
         * 查询年龄大于指定参数的用户信息并分页
         * @param page:必须放在第一个参数位置
         * @param age
         * @return
         */
        Page<User> selectPageByAge(@Param("page") Page<User> page, @Param("age") Integer age);
    
    }
    
  2. UserMapper.xml中编写具体的SQL语句:

    在配置文件中,设置Mapper接口的别名:

    mybatis-plus:
      #开通该配置后,当前包下的类的别名就是当前类名,且不区分大小写
      type-aliases-package: com.atguigu.mybatisplus.bean 
      
    
    
    DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.atguigu.mybatisplus.mapper.UserMapper">
    
       <select id="selectPageByAge" resultType="User">
            select * from user where age > #{age}
       select>
    
    mapper>	
    
  3. 测试:
    @Test
    public void testSelectPageByAge(){
        Page<User> page = new Page<>(2,2);
        userMapper.selectPageByAge(page,20);
        System.out.println("当前页数:" + page.getCurrent());
        System.out.println("每页记录数:" + page.getSize());
        System.out.println("总页数:" + page.getPages());
        System.out.println("总记录数:" + page.getTotal());
        System.out.println("当前页数据:" + page.getRecords());
    }
    

2、乐观锁插件

乐观锁:每次修改数据时,先判断版本号与自己之前取出的版本号是否相同,相同则修改成功,不相同则修改失败。
MyBatis Plus 自带乐观锁插件,只要简单的配置即可实现乐观锁功能。

  1. 创建表
    CREATE TABLE t_product ( 
        id BIGINT(20) NOT NULL COMMENT '主键ID', 
        NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称', 
        price INT(11) DEFAULT 0 COMMENT '价格', 
        VERSION INT(11) DEFAULT 0 COMMENT '乐观锁版本号', 
        PRIMARY KEY (id) 
    );
    
    插入一条数据:
    INSERT INTO t_product (id, NAME, price) VALUES (1, '外星人笔记本', 100);
    
  2. 创建实体类
    @Data
    public class Product {
    
        private Long id;
        private String name;
        private Integer price;
    
        @Version //标识当前字段为乐观锁版本号字段
        private Integer version;
    }
    
  3. 添加配置类
    @Configuration
    public class MyBatisPlusConfig {
    
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            //添加分页插件
            mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            //添加乐观锁插件
            mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return mybatisPlusInterceptor;
        }
    }
    
  4. 测试
    @Test
        public void testOptimisticLocker(){
            //小李查询商品价格
            Product productLi = productMapper.selectById(1);
            System.out.println("小李查询出的商品价格:" + productLi.getPrice()); //100
    
            //小王查询商品价格
            Product productWang = productMapper.selectById(1);
            System.out.println("小王查询出的商品价格:" + productWang.getPrice()); //100
    
            //小李修改商品价格
            productLi.setPrice(productLi.getPrice()+50);
            productMapper.updateById(productLi); //修改成功
            //实际执行SQL语句
            //UPDATE t_product SET name=?, price=?, version=? WHERE id=? AND version=?
    
            //小王修改商品价格
            productWang.setPrice(productWang.getPrice()-30);
            productMapper.updateById(productLi); //修改失败
    
            //老板最终查询出的商品价格
            Product productBoss = productMapper.selectById(1);
            System.out.println("老板最终查询出的商品价格:" + productBoss.getPrice()); //150
        }
    

八、通用枚举

  1. user表添加一个性别字段:
    mybatis-plus 学习笔记_第2张图片
  2. 创建一个性别枚举类:
    public enum SexEnum {
        FEMALE(0,"女"),
        MALE(1,"男");
    
        @EnumValue //将当前属性存入数据库中
        private Integer sex;
        private String sexName;
    
        SexEnum(Integer sex, String sexName) {
            this.sex = sex;
            this.sexName = sexName;
        }
    }
    
  3. User类添加性别属性:
    @Data
    public class User {
    
        private Integer id;
        private String name;
        private Integer age;
        private String email;
        private SexEnum sex;
    
        @TableLogic
        private Integer isDeleted;
    }
    
  4. 在配置文件中开启通用枚举扫描
    mybatis-plus:
      type-enums-package: com.atguigu.mybatisplus.enums
    
  5. 测试
    @Test
    public void testEnum(){
        User user = new User();
        user.setName("张三");
        user.setEmail("[email protected]");
        user.setAge(30);
        user.setSex(SexEnum.MALE);
    
        userMapper.insert(user);
    }
    

九、多数据源

适用于多种场景:纯粹多库、 读写分离、 一主多从、 混合模式等。

场景说明:
创建两个库,分别为:mybatis_plus(以前的库不动)与 mybatis_plus_1(新建),将mybatis_plus库的product表移动到mybatis_plus_1库,这样每个库一张表,通过一个测试用例分别获取用户数据与商品数据,如果获取到说明多库模拟成功。

1、创建数据库及表

  • 创建数据库 mybatis_plus_1 和表 t_product
    CREATE DATABASE mybatis_plus_1;
    USE mybatis_plus_1; 
    CREATE TABLE t_product ( 
        id BIGINT(20) NOT NULL COMMENT '主键ID', 
        name VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称', 
        price INT(11) DEFAULT 0 COMMENT '价格', 
        version INT(11) DEFAULT 0 COMMENT '乐观锁版本号', 
        PRIMARY KEY (id) 
    );
    
  • 添加测试数据
    INSERT INTO t_product (id, NAME, price) VALUES (1, '外星人笔记本', 100);
    
  • 删除 mybatis_plus 库中的 t_product 表
    USE mybatis_plus; 
    DROP TABLE IF EXISTS t_product;
    

2、新建一个工程

通过 Spring Initializr 新建一个 SpringBoot 工程,并选择 Lombok 和 MySQL 驱动。

引入 MyBaits-Plus 的依赖及多数据源的依赖:

<dependency>
    <groupId>com.baomidougroupId>
    <artifactId>mybatis-plus-boot-starterartifactId>
    <version>3.5.1version>
dependency>

<dependency>
    <groupId>com.baomidougroupId>
    <artifactId>dynamic-datasource-spring-boot-starterartifactId>
    <version>3.5.0version>
dependency>

3、填写配置文件

spring:
  # 配置数据源信息
  datasource:
    dynamic:
      # 设置默认的数据源或者数据源组,默认值即为master
      primary: master
      # 严格匹配数据源,默认false.true未匹配到指定数据源时抛异常,false使用默认数据源
      strict: false
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/mybatis_plus_1?serverTimezone=Asia/Shanghai
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: 123456
        slave_1:
          url: jdbc:mysql://localhost:3306/mybatis_plus_1?serverTimezone=Asia/Shanghai
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: 123456

4、创建实体类

User

@Data
public class User{
    
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    private Integer isDeleted;
    private Integer sex;
}

Product

@TableName(value ="t_product")
@Data
public class Product{

    @TableId
    private Long id;
    private String name;
    private Integer price;
    private Integer version;
}

5、编写 Mapper 接口

UserMapper

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

ProductMapper

@Mapper
public interface ProductMapper extends BaseMapper<Product> {
}

6、编写 Service 接口(指明数据源)

@DS 注解:指明数据源,可用在类上,也可用在方法上。

UserService

@DS("master")
public interface UserService extends IService<User> {
}

ProductService

@DS("slave_1")
public interface ProductService extends IService<Product> {
}

UserServiceImpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
}

ProductServiceImpl

@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService{
}

7、测试

@SpringBootTest
class MybatisPlusDsApplicationTests {

    @Autowired
    private UserService userService;

    @Autowired
    private ProductService productService;

    @Test
    void test() {
        User user = userService.getById(1);
        System.out.println(user);

        Product product = productService.getById(1);
        System.out.println(product);
    }
}

测试结果:
在这里插入图片描述

十、逆向工程

1、使用 FastAutoGenerator 类

mybatis_plus数据库中的user表:
mybatis-plus 学习笔记_第3张图片

  1. 创建一个新的 SpringBoot 工程并引入相关依赖
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>com.baomidougroupId>
        <artifactId>mybatis-plus-boot-starterartifactId>
        <version>3.5.1version>
    dependency>
    
    <dependency>
        <groupId>com.baomidougroupId>
        <artifactId>mybatis-plus-generatorartifactId>
        <version>3.5.1version>
    dependency>
    
    <dependency>
        <groupId>org.freemarkergroupId>
        <artifactId>freemarkerartifactId>
        <version>2.3.30version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <scope>runtimescope>
    dependency>
    
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    
  2. 填写配置文件
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=Asia/Shanghai
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password: gxm666
    
  3. 编写生成代码
    FastAutoGenerator.create("url", "username", "password")
        .globalConfig(builder -> {
            builder.author("baomidou") // 设置作者
                .enableSwagger() // 开启 swagger 模式
                .fileOverride() // 覆盖已生成文件
                .outputDir("D://"); // 指定输出目录
        })
        .packageConfig(builder -> {
            builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名
                .moduleName("system") // 设置父包模块名
                .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://")); // 设置mapperXml生成路径
        })
        .strategyConfig(builder -> {
            builder.addInclude("t_simple") // 设置需要生成的表名
                .addTablePrefix("t_", "c_"); // 设置过滤表前缀
        })
        .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
        .execute();
    
  4. 执行结果如下:
    mybatis-plus 学习笔记_第4张图片

2、使用 MyBatisX 插件(推荐)

mybatis_plus数据库中的user表:
mybatis-plus 学习笔记_第5张图片

  1. 创建一个 SpringBoot 工程并引入相关依赖
    <dependency>
        <groupId>com.baomidougroupId>
        <artifactId>mybatis-plus-boot-starterartifactId>
        <version>3.5.1version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <scope>runtimescope>
    dependency>
    
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    
  2. 打开 IDEA 插件市场,搜索mybatisx插件并安装;
  3. 在 IDEA 中配置 DataSource 数据源
    mybatis-plus 学习笔记_第6张图片
  4. 右键user,点击MyBatisX-Generator
    mybatis-plus 学习笔记_第7张图片
  5. 进行生成配置,然后点击Next
    mybatis-plus 学习笔记_第8张图片
  6. 进行模板配置,然后点击Finish
    mybatis-plus 学习笔记_第9张图片
  7. 生成结果如下:
    mybatis-plus 学习笔记_第10张图片

你可能感兴趣的:(java,学习,intellij-idea)