Mybatis-Plus学习

554 阅读5分钟

官方网站:点击进入

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>undefined</version>
</dependency>

1:测试环境

1.1:数据库创建

创建db_mybatis_plus数据库。再创建user表,user表如下

image.png

插入如下数据:

image.png

1.2:springboot项目创建

依赖引入

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
    </dependencies>

yml配置文件

spring:
  datasource:
    username: root
    password: yfy57609
    url: jdbc:mysql://1.15.57.103:3306/db_mybatis_plus?serverTimezone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver


#mybatis_plus日志配置
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

logback的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </encoder>
    </appender>

    <logger name="com.base22" level="TRACE"/>

    <root level="info">
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

mapper

记得要在启动类上@MapperScan注解

@Repository
public interface UserMapper extends BaseMapper<user> {
}

实体类

@Data
public class user {
    private int id;
    private String name;
    private Integer age;
    private String email;
}

2:ybatis_plus的增删改查

21:简单插入

 @Test
    public void insert(){
        user u=new user();
        u.setName("aaa");
        u.setAge(21);
        u.setEmail("1234@qq.com");
        int result=userMapper.insert(u);
        System.out.println("影响的行数:"+result);
        System.out.println("user id:"+u.getId());
    }
    输出:
    影响的行数:1
    user id:1412739741353529345

值得注意的问题: 数据库的id主键并没有设置自增,而且插入时user的id的值应该默认是0.但是插入后为什么会赋予一个1412739741353529345的主键?

分库分表策略

业务分库:将一个数据库按照业务功能的区分分为几个数据库 分库 代价:join无法使用,涉及多个数据库的事务无法使用

主从复制 :主机进行写操作,从机进行读操作

数据库分表: 不同的业务数据坟山储存到不同的数据库服务器。垂直拆分(字段列)或者水平(数据行)拆分

水平拆分-主键自增策略: 每个表存储一定区间的数据,例如表一id位1-999999,表二为100000-199999。缺点是每个表的大小可能不一,一个表可能有1000条数据(这个id区间的数据大部分被删除了),一个表有9万条数据。

水平拆分-hash策略: 比如有十个表,通过id%10的值来决定放在哪个表中,比如id=15的数据放到编号5的表中.难点在于数据库的数量的选取。优点是数据分布均匀。缺点是扩充新的表比较困难

雪花算法:分布式ID生成器: 保证不同表的主键的不重复性,以及相同表的主键的有序性 image.png

image.png

mybatis_plus的主键策略

默认使用雪花算法.数据库不用设置主键自增

还有主键自增策略:数据库要设置为主键自增。代码的自增差旅也要修改,如下

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

全局设置主键生成策略(在配置文件中):

mybatis-plus:
 global-config:
   db-config:
     id-type: auto

2.2:更新操作

通过id修改数据

@Test
    public void update(){
       user u=new user();
       u.setId(0l);
       u.setAge(30);
       int result=userMapper.updateById(u);
        System.out.println("影响的行数:"+result);
        System.out.println(u.toString());
    }

开发规范,习惯。设置数据的创建和更新时间

数据库表修改如下:

image.png

实体类也做修改,添加字段:

@Data
public class user {
    private Long id;
    private String name;
    private Integer age;
    private String email;

    private Date createTime;//驼峰自动转换
    private Date updateTime;
}

业务层添加创建时间和修改更新时间可以通过mybatis_plus的自动填充功能实现,而无需每次手动去设置

自动填充功能

该功能可以用来实现例如添加创建时间和修改更新时间

首先在实体类上添加自动填充注解到要主动填充的字段上面:

@Data
public class user {
    private Long id;
    private String name;
    private Integer age;
    private String email;

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;//驼峰自动转换

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

然后实现元对象处理接口:

一般放在handler包下

@Slf4j(topic = "mybatis_plus自动填充")
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
        log.info("插入一个数据,自动填充创建时间和更新时间");
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
        log.info("更新数据,自动填充更新时间");
    }
}

现在便可以自动设置对象(这里是user)的某些字段值了。这里传入的metaObject其实就是我们调用插入或者更新方法传入的对象,例如userMapper.insert(user),在调用插入后,就会自动为这个user填充插入时间和更新时间,而不需要我们手动调用setter方法。上面的meteObject里面就包含这个user。setFieldValByName方法就是为meteObject里面的对象的相应字段设置相应值。通俗点说这里就是自动调用setter方法设置一个值

2.3:乐观锁

首先要注入插件,使用springboot配置方式

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
   MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
   interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
   return interceptor;
}

在实体类的字段上加上@Version注解

@Version
private Integer version;

image.png

2.4:基本查询

2.4.1:批量查询

  @Test
    public void Beach(){
       List<user> userList= userMapper.selectBatchIds(Arrays.asList(1,2,3));
        log.info(String.valueOf(userList));
    }

2.4.2:条件查询

@Test
    public void select(){
        Map<String,Object> map=new HashMap<>();
        map.put("name","yfy");
        map.put("age",30);
        List<user> users=  userMapper.selectByMap(map);
        log.info(String.valueOf(users));
    }

2.4.3:分页查询

先配置分页插件

 @Bean
    public PaginationInterceptor mybatisPlusInterceptor() {
        return new PaginationInterceptor();
    }
    

测试

 @Test
    public void selectPage(){
        Page<user> page=new Page<>(1,5);
        Page<user> pageParam = userMapper.selectPage(page, null);
        List<user> users=pageParam.getRecords();
        log.info(String.valueOf(users));
        System.out.println("总页数"+pageParam.getPages());
        System.out.println("总记录数"+pageParam.getTotal());
        System.out.println("当前页"+pageParam.getCurrent());
        System.out.println("每页记录数"+pageParam.getSize());
        System.out.println("是否有下一页"+pageParam.hasNext());
        System.out.println("是否有上一页"+pageParam.hasPrevious());
    }

补充

image.png

2.5:删除

物理删除

  @Test
    public void delete(){
        //根据id删除
        userMapper.deleteById(0);
        //批量删除
        userMapper.selectBatchIds(Arrays.asList(1,2,3));
        //自定义删除条件
        Map<String,Object> map=new HashMap<>();
        map.put("name","yfy");
        userMapper.deleteByMap(map);
    }

逻辑删除

增加逻辑删除标志

image.png

image.png

   @Test
   public void logdelete(){
       userMapper.deleteById(1);
   }

image.png 这样删除时进行的是update操作

3:条件构造器

条件构造器