mybatis-plus学习


title: mybatis-plus学习
date: 2020-10-21 23:58:34
tags:

  • java
    categories:
  • java

mybatis-plus学习

本文介绍了mybatis-plus的基本方法及学习,详情请参考官方中文文档

可以参考代码生成器的配置参数

复习mybatis用法

  1. 依赖
  2. @Mapper注解,表名为mapper接口类,可在此类上使用注解写sql语句
  3. Controller层注入mapper类,并使用对象进行增删改查
  4. xml需要配置mybatis全局文件,并设置对应的mapper.xml

快速开始

数据库准备

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);
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');

依赖

导入mybatis-plus-boot-starter,注意,尽量不要同时导入mybatis和mybatis-plus,可能存在版本差异

配置

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver

pojo

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "User",description = "用户实体类")
public class User {
    @Length(min = 0,max = 10000)
    @ApiModelProperty(notes = "自增列id",dataType = "int")
    private Long id;
    @NotNull(message = "姓名不能为空")
    @ApiModelProperty(notes = "姓名",dataType = "String")
    private String name;
    @Length(min = 0,max = 200,message = "年龄不能超过200")
    @ApiModelProperty(notes = "年龄",dataType = "int")
    private int age;
    @Email(message = "邮箱格式错误")
    @ApiModelProperty(notes = "邮箱",dataType = "String")
    private String email;
}

mapper

@Repository
public interface UserMapper extends BaseMapper<User> {

}

test

@Test
void contextLoads() {
    //查询所有用户
    // 参数是mapper,条件构造器,不用的情况下可以用null代替
    List<User> users = userMapper.selectList(null);
    users.forEach(System.out::println);
}

日志

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

主键生成策略

uuid,自增id,雪花算法,redis,zookeeper(分布式系统唯一id生成)-> @TableId(type = IdType.AUTO)

IdType默认ID_WORKER,详情请到源码里查看

注意:使用AUTO主键自增时,对应数据库字段也必须为auto_increment

自动填充字段

数据库级别

直接使用alter table xxx modify column xxx datetime current_timestamp on update current_timestamp进行数据库层面的操作

代码级别

首先删除所有的字段的自更新操作(除主键)

再在实体类上

@TableField(fill = FieldFill.INSERT)
private Data createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Data updateTime;

其次编写处理器handler

@Slf4j
@Component
public class MetaMybatisHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill");
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

乐观锁

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

乐观锁插件

  1. 数据库字段设置version字段

  2. 实体类添加字段

    @Version //乐观锁注解
    private Integer version;
    
  3. 注册组件

    @Configuration
    @EnableTransactionManagement
    @MapperScan("com.learnmybatis.plusdemo")
    public class MybatisPlusConfig {
        //注册乐观锁插件
    //    @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor() {
            return new OptimisticLockerInterceptor();
        }
    }
    
  4. 测试

    @Test
    public void  testOptimisticLocker1(){
        // 线程1
        User user = userMapper.selectById(2L);
        user.setName("learn001");
        user.setEmail("223311@qq.com");
        // 线程2, 都对2L进行操作
        User user1 = userMapper.selectById(2L);
        user1.setName("learn002");
        user1.setEmail("test@qq.com");
        // 设置了乐观锁的情况下,user线程1失败(不抛异常,可以通过检测version->返回值进行检测是否触发乐观锁)
        userMapper.updateById(user1);
        userMapper.updateById(user);
    }
    

查询与分页查询

批量查询

@Test
public void testSelectBatchId(){
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1L,2L,3L));
    users.forEach(System.out::println);
    System.out.println("------------------");
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("name","java1");
    List<User> userList = userMapper.selectByMap(hashMap);
    userList.forEach(System.out::println);
}

分页查询

  1. 配置分页拦截器

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
    
  2. 测试类

    @Test
    public void testPage(){
        // 当前页,页面大小
        Page<User> page = new Page<>(1,5);
        userMapper.selectPage(page,null);
        page.getRecords().forEach(System.out::println);
        System.out.println("-----------------------");
        page.setCurrent(2).setSize(5).getRecords().forEach(System.out::println);
    }
    

删除

普通删除

@Test
public void testDelete(){
    userMapper.deleteById(1L);
    userMapper.deleteBatchIds(Arrays.asList(2L,3L));
    HashMap<String, Object> map = new HashMap<>();
    map.put("name","java2");
    userMapper.deleteByMap(map);
}

物理删除:从数据库里删除

逻辑删除:设置删除字段

逻辑删除

  1. 设计数据库删除字段

  2. 实体类@TableLogic注解

  3. 配置config(高版本不需要)

  4. 配置文件修改

    mybatis-plus:
      global-config:
        db-config:
          logic-delete-field: flag  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
          logic-delete-value: 1 # 逻辑已删除值(默认为 1)
          logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
    
  5. 查询后会过滤已删除的数据

条件查询

条件查询官网参考

@Test
public void testWrapper(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.isNotNull("name").isNotNull("email")
        .ge("age","10");
    List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
}

代码自动生成器

public class GeneratorCode {
    public static void main(String[] args) {
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("jhWu");
        gc.setOpen(false);
        gc.setFileOverride(false);
        gc.setServiceName("%sService");
        // 数据库配置
        gc.setIdType(IdType.AUTO);
        gc.setDateType(DateType.ONLY_DATE);
        // gc.setSwagger2(true); 实体属性 Swagger2 注解
        mpg.setGlobalConfig(gc);
        // 数据源配置
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
//        getDataSource dataSource = new getDataSource();
        dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mybatis-plus?serverTimezone=UTC&useSSL=false");
        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSourceConfig.setUsername("root");
        dataSourceConfig.setPassword("123456");
        dataSourceConfig.setDbType(DbType.MYSQL);
        mpg.setDataSource(dataSourceConfig);
        // 包的配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setModuleName("blog");
        packageConfig.setParent("com.learnmybatis.plusdemo");
        packageConfig.setEntity("entity");
        packageConfig.setService("service");
        packageConfig.setController("controller");
        mpg.setPackageInfo(packageConfig);
        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user");
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//        strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
        strategy.setLogicDeleteFieldName("deleted");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        // 自动填充配置
        TableFill createTime = new TableFill("createTime", FieldFill.INSERT);
        TableFill modifyTime = new TableFill("modifyTime", FieldFill.INSERT_UPDATE);
        strategy.setTableFillList(Arrays.asList(createTime,modifyTime));
        // 乐观锁
        strategy.setVersionFieldName("version");
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);
        mpg.setStrategy(strategy);
        mpg.execute();
    }
}
上一篇:解锁新姿势:探讨复杂的 if-else 语句“优雅处理”的思路


下一篇:JPA实体注解与hibernate主键生成策略