MybatisPlus技术

一.MybatisPlus的快速入门

(1)开发环境

              IDEA:IntelliJ IDEA 2021.3.3
              JDK:14.0.2
              MySql:
              SpringBoot:2.6.7
              MyBatis_Plus:3.5.1

(2)创建数据库的表和对应的实体类

创建表和插入数据的sql语句

CREATE DATABASE `mybatis_plus` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
USE `mybatis_plus`;
CREATE TABLE `user` (
`id` BIGINT(20) NOT NULL COMMENT '主键ID',
`name` VARCHAR(30) DEFAULT NULL COMMENT '姓名',
`age` INT(11) DEFAULT NULL COMMENT '年龄',
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
 PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

 INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

 创建实体类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private long id;
    private String name;
    private Integer age;
    private String email;
}

(3)创建SpringBoot工程

        导入依赖

<dependencies>
        <!--mybatis-plus场景启动器依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--lombok依赖用于简化实体类开发,注意这个lombok是需要下载插件的-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--数据库驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--默认添加的依赖:spring-boot场景启动器依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--默认添加的依赖:spring-boot测试功能的场景启动器依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

         配置SpringBoot的application.yml

spring:
  #配置数据源信息
  datasource:
    #配置数据源类型
    type: com.zaxxer.hikari.HikariDataSource
    #配置链接数据库的各个信息
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&userSSL=false
    username: root
    password: root
    

注意:

1.驱动类driver-class-name:
spring boot 2.0(内置jdbc5驱动),驱动类使用:
driver-class-name: com.mysql.jdbc.Driver
spring boot 2.1及以上(内置jdbc8驱动),驱动类使用:

driver-class-name: com.mysql.cj.jdbc.Driver
否则运行测试用例的时候会有 WARN 信息
2.连接地址url MySQL5.7版本的url:
jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
MySQL8.0版本的url:

jdbc:mysql://localhost:3306/mybatis_plus?
serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
否则运行测试用例报告如下错误:
java.sql.SQLException: The server time zone value ‘Öйú±ê׼ʱ¼ä’ is unrecognized or represents more

        写mapper接口继承BaseMapper,并且启动类扫描

@Component
public interface UserMapper extends BaseMapper<User> {
}
@SpringBootApplication
@MapperScan("com.example.mybatisplus_demo.mapper")//扫描mapper接口所在的包
public class MyBatisPlusDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBatisPlusDemoApplication.class, args);
    }
}

(4)测试

@SpringBootTest
class MyBatisPlusDemoApplicationTests {
    @Autowired
    UserMapper userMapper;
    @Test
    void contextLoads() {
        List<User> users = userMapper.selectList(null);
        System.out.println(users);
    }
}

(5)[拓展]添加日志功能

其实只需要在配置文件中加上配置信息就行

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

 二.增删改查功能的实现

 (1)Dao层基础的单表CRUD:    

 @Autowired
    UserMapper userMapper;

    @Test//查询记录
    void test4() {
        /*共10种,先测试3种,带Wrapper条件的先不测*/
        User user = userMapper.selectById(1L);//第一种
        System.out.println(user);
        List<Long> ids = Arrays.asList(3L, 4L);//第二种,SELECT id,name,age,email FROM user WHERE id IN ( ? , ? )
        List<User> users = userMapper.selectBatchIds(ids);
        System.out.println(users);
        Map<String,Object> map=new HashMap<>();map.put("name","萧萧");map.put("age",2000);
        userMapper.selectByMap(map);//第三种
    }

    @Test//修改记录
    void test3() {
        /*共两种,先测试一种,带Wrapper条件的先不测*/
        User user = new User(1L,"萧萧", 2000, "xiaoxiao@123.com");
        userMapper.updateById(user);
    }
    @Test//删除记录
    void test2() {
        /*共五种,先测试四种,带Wrapper条件的先不测*/
        userMapper.deleteById(1);//第一种
        userMapper.deleteById(new User(2L));//第二种
        Map<String,Object> map=new HashMap<>();map.put("name","萧萧");map.put("age",2000);
        userMapper.deleteByMap(map);//第三种
        List<Long> ids = Arrays.asList(3L, 4L);
        userMapper.deleteBatchIds(ids);//第四种:DELETE FROM user WHERE id IN ( ? , ? )
    }
    @Test//添加记录
    void test1() {
        User user = new User("萧萧", 2000, "xiaoxiao@123.com");
        int result = userMapper.insert(user);//会增加一条记录,并且自动生成id,将id赋值给该对象的id属性
        System.out.println(result);
        System.out.println("id"+user.getId());//id是雪花算法自动生成的,
    }

(2)自定义功能

      这里的步骤就跟Mybatis中一样了,但是有几个点要注意。首先mapper映射文件有默认的路径(也就是在resources/mapper下写映射文件),可以在yml配置文件中进行自己配置。

    @Test//自定义
    void test5() {
        Map<String, Object> stringObjectMap = userMapper.selectMapById(1L);
        System.out.println(stringObjectMap);
    }
 <select id="selectMapById" resultType="map">
        select * from user where id=#{id}
    </select>

自己配置除了要在配置文件中加上面的代码,还要在pom.xml中加上:

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

 (3)Service层封装的单表CRUD:

     继承和实现体系

     在IService<T>接口中封装了CRUD的方法,而ServiceImpl<M extends BaseMapper<T>, T> implements IService<T>是它的实现类。
     如果我们想要使用这个,我们需要新建一个接口UserService去继承IService<T>接口,同时UserService的实现类UserServiceImpl还要继承ServiceImpl,省得重写方法。

//继承接口
public interface UserService extends IService<User> {
}

//实现自定义接口
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
}

     简单的测试

    @Autowired
    UserServiceImpl userService;

    @Test//简简单单,只测试两个方法
    void test() {
        //查询总记录数
        long count = userService.count();
        System.out.println(count);
        //批量添加
        List<User> list =new ArrayList<>();
        for(int i=1;i<=5;i++){
            User user = new User();
            user.setName("xiaoxiao"+i);
            user.setAge(20+i);
            list.add(user);
        }
        boolean b = userService.saveBatch(list);
        System.out.println(b);
    }

(4)条件构造器Wrapper

 1.QueryWrapper

简单的删改查

  @Test
    public void test(){
        //删除,查询都要用QueryWrapper
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<User>();
        userQueryWrapper.eq("user_name","萧萧");//等于
        userQueryWrapper.ge("uid",1); //ge是大于等于,le小于等于
        userQueryWrapper.le("uid",4);
        userQueryWrapper.isNotNull("user_name");
        //Asc是升序,Desc是降序
        //先按照age升序排序,相同的话就按照uid的降序排序
        userQueryWrapper.orderByAsc("age").orderByDesc("uid");
        List<User> users = userMapper.selectList(userQueryWrapper);
        System.out.println(users);
    }

    @Test
    public void test2(){//修改操作
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        //ge是>=  le是<=  gt是>  lt是<
        //把年纪大于等于12并且名字中带a的人 或者 email是空的人进行修改
        userQueryWrapper.ge("age",12)
                .like("user_name","a")
                .or()
                .isNull("email");
        User user = new User();
        user.setName("小明");
        user.setEmail("xiaoming@123.com");
        //UPDATE t_user SET user_name=?, email=? WHERE is_deleted=0 AND (age >= ? AND user_name LIKE ? OR email IS NULL)
        userMapper.update(user,userQueryWrapper);
    }

 条件优先级

    @Test
    public void test3(){//修改操作。优先级
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        //ge是>=  le是<=  gt是>  lt是<
        //把名字中带a的人并且(年纪大于等于12或者email是空)的人进行修改
        //lambda中的条件优先执行
        userQueryWrapper
                .like("user_name","明")
                .and(i->i.ge("age",12).or().isNull("email"));
        User user = new User();
        user.setName("小红");
        user.setEmail("xiaoming@123.com");
        //UPDATE t_user SET user_name=?, email=? WHERE is_deleted=0 AND (user_name LIKE ? AND (age >= ? OR email IS NULL))
        userMapper.update(user,userQueryWrapper);
    }

 组装select语句:也就是只查询自己想要的字段。

    @Test//组装select字句
    public void test4(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.select("uid","user_name");
        List<Map<String, Object>> maps = userMapper.selectMaps(userQueryWrapper);
        System.out.println(maps);
    }

组装子查询

    @Test//组装select字句
    public void test4(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.select("uid","user_name");
        List<Map<String, Object>> maps = userMapper.selectMaps(userQueryWrapper);
        System.out.println(maps);
    }

2. UpdateWrapper

简单的修改操作

    @Test//UpdateWrapper
    public void test6(){
        //把名字中带a的人并且(年纪大于等于12或者email是空)的人进行修改
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.like("user_name","红")
                .and(i->i.ge("age",12).or().isNull("email"))
                .set("user_name","小黑").set("email","xiaohei@guigu.com");
        userMapper.update(null,userUpdateWrapper);

    }

模拟开发环境中组装条件的情况

    @Test
    public void test7(){
        String username=" ";
        Integer ageBegin=20;
        Integer ageEnd=50;
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        if(StringUtils.isNotBlank(username)){
            userQueryWrapper.like("username",username);
        }
        if(ageBegin!=null){
            userQueryWrapper.ge("age",ageBegin);
        }
        if(ageEnd!=null){
            userQueryWrapper.le("age",ageEnd);
        }
        List<User> users = userMapper.selectList(userQueryWrapper);
        System.out.println(users);
    }

上述的情况还有另一种解决的方法

    @Test
    public void test8(){
        String username=" ";
        Integer ageBegin=20;
        Integer ageEnd=50;
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper
                .like(StringUtils.isNotBlank(username),"username",username)
                .ge(ageBegin!=null,"age",ageBegin)
                .le(ageEnd!=null,"age",ageEnd);
        //SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name LIKE ? AND age >= ? AND age <= ?)
        List<User> users = userMapper.selectList(userQueryWrapper);
        System.out.println(users);
    }

3.LambdaWrapper

    @Test//LambdaQueryWrapper
    public void test9(){
        String username=" ";
        Integer ageBegin=20;
        Integer ageEnd=50;
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.like(StringUtils.isNotBlank(username),User::getName,username)
                        .ge(ageBegin!=null,User::getAge,ageBegin)
                        .le(ageEnd!=null,User::getAge,ageEnd);
        //SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (age >= ? AND age <= ?)
        List<User> users = userMapper.selectList(userLambdaQueryWrapper);
        System.out.println(users);
    }

   @Test//LambdaUpdateWrapper
    public void test10(){
        String username=" ";
        Integer ageBegin=21;
        Integer ageEnd=21;
        LambdaUpdateWrapper<User> objectLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        objectLambdaUpdateWrapper.like(StringUtils.isNotBlank(username),User::getName,username)
                .ge(ageBegin!=null,User::getAge,ageBegin)
                .le(ageEnd!=null,User::getAge,ageEnd);
        //SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (age >= ? AND age <= ?)
        List<User> users = userMapper.selectList(objectLambdaUpdateWrapper);
        System.out.println(users);
    }

三.常用注解

(1)@TableName

聪明的小伙伴已经发现了,要是表名和实体类名不一样就会报错,有两个办法可以解决这个问题:

1.在类名上面加上注解@TableName

@TableName("t_user")//这里面的是数据库中的表名
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
    public User(String name, Integer age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }
    public User(Long id) {
        this.id = id;
    }
}

2.在配置文件中进行全局配置

(2)@TableId

    Mybatis_plus会默然把类中的id作为主键,但是我们有是有为了数据库中字段名和实体类的属性相匹配,就会出现uid、tid等属性名。如果不给对象的uid属性赋值,就把这个对象插入进数据库里,Mybatis_plus不会对uid属性自动赋值,但是uid是数据库中的主键,就会报错。

在uid属性上面加该注解

public class User {
    @TableId//将属性对应的数据库中字段定义为主键
    private Long uid;
}

该注解的两个属性

如果数据库中是uid,类中属性名是id,要匹配呀!就要用到该注解的value属性

public class User {
    @TableId(value="uid")//value属性表示,id这个属性对应数据库中的uid字段
    private Long id;
}

主键的生成策略是可以改变的!可以使用该注解,当然也可以使用全局配置来设置生成策略:

public class User {
    //value属性表示,id这个属性对应数据库中的uid字段
    //type属性用于设置id的生成策略,ASSIGN_ID是雪花算法,AUTO是自增
    //type= IdType.AUTO使用该type的前提是数据库中要设置成自增,不然会报错
    //如果手动给id赋值的话是不会调用该雪花算法的
    @TableId(value="uid",type= IdType.AUTO)
    private Long id;
}

(3)TableField

     当主键之外的字段名和属性名不匹配的时候,会用到该注解。比如,字段名是user_name,属性名是username。注意如果这里属性名是userName,不会出问题,因为有默认的驼峰映射关系。

    @TableField("user_name")//这里面的字符串就是字段名
    private String name;

(4)TableLogic

   这个是用于逻辑删除。首先在数据库中添加is_deleted,默认值设置为0表示未删除,1表示已经删除。

    @TableLogic
    private  Integer isDeleted;

四.其他功能

(1)分页插件

需要一个配置类去配置:

@Configuration
@MapperScan("com.example.mybatisplus_demo.mapper")//扫描mapper接口所在的包
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}

测试代码如下:

@SpringBootTest
public class plugins_test {
    @Autowired
    UserMapper userMapper;
    @Test
    public void testPage(){
        Page<User> userPage = new Page<>(1,3);//访问第一页,每页显示三条数据
        userMapper.selectPage(userPage,null);//进行分页查询
        System.out.println(userPage);
        //分页相关数据获取
        System.out.println(userPage.getRecords());//获取查到的某一页记录
        System.out.println(userPage.getPages());//获取总记录数
        System.out.println(userPage.getTotal());//获取总页数
        System.out.println(userPage.hasNext());//是否有下一个
        System.out.println(userPage.hasPrevious());//是否有上一个
    }
}

自定义分页功能:

 //通过年龄来查询数据
    Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);
    <!--Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);-->
    <select id="selectPageVo" resultType="User">
        select * from t_user where age>#{age}
    </select>

    @Test//自定义分页功能测试代码
    public void testPageVo(){
        Page<User> userPage = new Page<>(1,3);//访问第一页,每页显示三条数据
        userMapper.selectPageVo(userPage,22);//进行分页查询
        //select * from t_user where age>? LIMIT ?
        System.out.println(userPage);
    }

(2)乐观锁插件

        场景:两个人对售价100的商品进行修改,小李要加50小王要减30,最后期望的价格应该是120。但是如果不加锁:两个人同时取出数据100,小李加了50元,将150元的价格存到了数据库。这个时候,小王对他拿到的数据进行修改,得到70覆盖掉了150元。这就出现了问题
        乐观锁和悲观锁:乐观锁的话小王在保存数据之前会查看价格是否被修改过了,若果被改过那么就取出被修改过的价格,然后再进行修改,这样就会使结果正确。如果是悲观锁,小李取出数据之后,小王只能在小李才做完之后才能够对价格进行操作,这样也能保证价格的正常。

乐观锁实现

创建个表,然后添加数据:

添加实体类:

@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    private Integer version;
}

添加mapper并测试

    @Autowired
    ProductMapper productMapper;
    @Test//现在是不是使用乐观锁,原本价格是500,本次操作后价格是470
    public void test2(){
        //小李查询商品价格
        Product product1 = productMapper.selectById(1);
        System.out.println("小李查到的价格是:"+product1.getPrice());
        //小王查到的商品价格
        Product product2 = productMapper.selectById(1);
        System.out.println("小王查到的价格是:"+product2.getPrice());
        //小李修改价格
        product1.setPrice(product1.getPrice()+50);
        productMapper.updateById(product1);
        //小李王修改价格
        product2.setPrice(product2.getPrice()-30);
        productMapper.updateById(product2);
        //老板来查数据
        Product product3 = productMapper.selectById(1);
        System.out.println(product3.getPrice());
    }

 添加乐观锁:

    //在实体类的属性上添加注解
    @Version//标志着这是一个乐观锁版本号的属性
    private Integer version;
//在配置类里面添加乐观锁插件
@Configuration
@MapperScan("com.example.mybatisplus_demo.mapper")//扫描mapper接口所在的包
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //添加分页插件
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        //添加乐观锁插件
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}
@Test//现在是使用乐观锁,原本价格是100,本次操作后价格是120
    public void test2(){
        //小李查询商品价格
        Product product1 = productMapper.selectById(1);
        System.out.println("小李查到的价格是:"+product1.getPrice());
        //小王查到的商品价格
        Product product2 = productMapper.selectById(1);
        System.out.println("小王查到的价格是:"+product2.getPrice());
        //小李修改价格
        product1.setPrice(product1.getPrice()+50);
        productMapper.updateById(product1);
        //小李王修改价格
        product2.setPrice(product2.getPrice()-30);
        int result = productMapper.updateById(product2);
        if(result==0){
            //操作失败,重试
            Product productNew = productMapper.selectById(1);
            productNew.setPrice(productNew.getPrice()-30);
            productMapper.updateById(productNew);
        }
        //老板来查数据
        Product product3 = productMapper.selectById(1);
        System.out.println(product3.getPrice());
    }

(3)通用枚举

1.在数据库中添加一个sex字段,int类型
2.写个枚举类型:

@Getter
public enum SexEnum{
    MALE(1,"男"),
    FEMALE(2,"女");
    @EnumValue//将注解所标识的属性的值存储到数据库中
    private Integer sex;
    private String sexName;
    SexEnum(Integer sex,String sexName){
        this.sex=sex;
        this.sexName=sexName;
    }
}

3.在配置文件里扫描通用枚举的注解:

 4.测试:

    @Test
    public void test4(){
        User user = new User();
        user.setName("aehfw");
        user.setAge(33);
        user.setSex(SexEnum.MALE);
        userMapper.insert(user);
    }

五.代码生成器

(1)简简单单生成个代码

1.引入依赖

<!--代码生成器依赖-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.1</version>
</dependency>
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
</dependency>

2.java代码:

public class FastAutoGeneratorTest {
    public static void main(String[] args) {
        //连接数据库的信息
        FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis_plus?characterEncoding=utf-8&userSSL=false", "root", "root")
                .globalConfig(builder -> { //进行全局配置
                    builder.author("atguigu") // 设置作者
                            //.enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件,重新生成代码
                            .outputDir("D://mybatis_plus"); // 指定输出目录
                })
                .packageConfig(builder -> { //设置当前的包
                    builder.parent("com.atguigu") // 设置父包名
                            .moduleName("mybatisplus") // 设置父包模块名,也就是说当前生成的所有内容都在com.atguigu.mybatisplus包下。
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> { //策略配置
                    builder.addInclude("t_user") // 设置需要生成的表名
                            .addTablePrefix("t_", "c_"); // 设置过滤表前缀
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
}

(2)MyBatisX插件

插件的用法:https://baomidou.com/pages/ba5b24/

快速生成体系结构

1.创建springboot项目

2.引依赖

3.写配置文件

4.先测试能不能连接到数据库

    <dependencies>
        <!--mybatis-plus场景启动器依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--lombok依赖用于简化实体类开发,注意这个lombok是需要下载插件的-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--数据库驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--默认添加的依赖:spring-boot场景启动器依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--默认添加的依赖:spring-boot测试功能的场景启动器依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

spring:
  # 配置数据源信息
  datasource:
    # 配置数据源类型
    type: com.zaxxer.hikari.HikariDataSource
    # 配置连接数据库信息
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
    username: root
    password: root

 

 5.开始使用:

 

 

 快速生成CRUD:

六.多数据源

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

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

1.创建数据库和表,添加数据

CREATE DATABASE `mybatis_plus_1` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
USE `mybatis_plus_1`;
CREATE TABLE 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 product (id, NAME, price) VALUES (1, '外星人笔记本', 100);

2. 在上面依赖的基础上添加新的依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.5.0</version>
</dependency>

3.配置多数据源:

spring:
  # 配置数据源信息
  datasource:
    dynamic:
      # 设置默认的数据源或者数据源组,默认值即为master
      primary: master
      # 严格匹配数据源:
      #  false(默认):如果当前匹配不到数据源的时候它会使用当前的默认数据源
      #  true:未匹配到指定数据源时抛异常
      strict: false
      datasource:
        #主数据源的信息,名字和primary的值保持一致。
        master:
          url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: root
        #从数据源的信息
        slave_1:
          url: jdbc:mysql://localhost:3306/mybatis_plus_1?characterEncoding=utf-8&useSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: root
 

4.写实体类:

@Data
@TableName("t_user")
public class User {
    @TableId
    private Integer uid;
    private String userName;
    private Integer age;
    private Integer sex;
    private String email;
    private Integer isDeleted;
}

@Data
public class Product {
    private Integer id;
    private String name;
    private Integer price;
    private Integer version;
}

5.写Service

public interface UserService extends IService<User> {
}

@Service
@DS("master")//使用某个数据源
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

public interface ProductService extends IService<Product> {
}

@Service
@DS("slave_1")
public class ProductServiceImpl extends ServiceImpl<ProductMapper,Product> implements ProductService{
}

6.写mapper

@Component//记得在启动类上进行mapper的包扫描
public interface UserMapper extends BaseMapper<User> {
}
@Component
public interface ProductMapper extends BaseMapper<User> {
}

7.测试

@SpringBootTest
class MybatisPlusDatasourceApplicationTests {

    @Autowired
    private UserService userService;
    @Autowired
    private ProductService productService;

    @Test
    public void test(){
        System.out.println(userService.getById(1));
        System.out.println(productService.getById(1));
    }

}

七.结论:

(1)最后的项目结构:

 (2)所有的坐标:

    <dependencies>
        <!--mybatis-plus场景启动器依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--lombok依赖用于简化实体类开发,注意这个lombok是需要下载插件的-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--数据库驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--默认添加的依赖:spring-boot场景启动器依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--默认添加的依赖:spring-boot测试功能的场景启动器依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--代码生成器依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>
    </dependencies>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值