首页 > 其他 > 详细

MyBatis-Plus

时间:2020-05-01 09:52:57      阅读:62      评论:0      收藏:0      [点我收藏+]

MyBatis-Plus

简介

为简化开发而生!是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变。

润物无声:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。

效率至上:只需简单配置,即可快速进行 CRUD 操作,从而节省大量时间。

丰富功能:热加载、代码生成、分页、性能分析等功能一应俱全。

愿景:是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。

技术分享图片

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作, BaseMapper
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求, 以后简单的CRUD操作,它不用自己编写了!
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题支持
  • ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大 的 CRUD操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(自动帮你生成代码)
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、 Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、update 操作智能分析阻断,也可自定义拦截规则,预防误操作

快速入门

  1. 创建mybatis_plus数据库,创建user表,插入测试数据:
DROP TABLE IF EXISTS user;

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‘); 
  1. 创建mybatis_plus的SpringBoot工程,在pom文件中导入mybatis-plus的依赖包。
		<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
		 </dependency>

导入其他数据源的包,web启动包,lombok。

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
  1. 修改application.yml,配置数据源。
spring:
  datasource:
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    type: com.alibaba.druid.pool.DruidDataSource
  1. 编写entity
@Data 
@AllArgsConstructor 
@NoArgsConstructor 
public class User {
 ? ?private Long id; ? ?
    private String name; ? ?
    private Integer age; ? ?
    private String email;
}
  1. 编写mapper接口
//继承了BaseMapper,所有简单的CRUD操作都已经编写完成了 
public interface UserMapper extends BaseMapper<User> {
}
  1. 编写一个MyBatisPlusConfig:
@MapperScan("com.yinrz.mapper") // 扫描我们的 mapper 文件夹
@Configuration // 配置类
public class MyBatisPlusConfig {
}
  1. 写一个测试类进行测试:
@SpringBootTest
public class MybatisPlusApplicationTests{
    @Resource
    UserMapper userMapper;

    @Test
    public void test01(){
        List<User> users = userMapper.selectList(null);
        for (User user:users){
            System.out.println(user);
        }
    }
}

运行结果:

技术分享图片

insert插入操作

    @Test
    public void testInsert() {
        User user = new User();
        user.setName("yinrz");
        user.setAge(18);
        user.setEmail("1760266861@qq.com");
        int result = userMapper.insert(user);
        System.out.println(result); // 受影响的行数 ? ?
        System.out.println(user); // 发现id会自动回填
    }

技术分享图片

**我们发现id会自动回填 **

数据库插入的id的默认值为: ID_WORKER 全局的唯一id(雪花算法)

分布式系统唯一ID生成方法总汇:https://www.cnblogs.com/haoxinyue/p/5208136.html

我们可以修改插入的id的生成策略

  1. 在实体类的id字段上添加注解@TableId,指定type=IdType.xxx,例如@TableId(type = IdType.AUTO),数据库要开启主键自增!!!
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
  1. id生成策略:
public enum IdType { ? ?
    AUTO(0), // 数据库id自增(数据库要开启主键自增!!!) ? ?
    NONE(1), // 未设置主键 ? ?
    INPUT(2), // 手动输入 ? ?
    ID_WORKER(3), // 全局唯一id(默认)
    UUID(4), // 全局唯一id,uuid ? ?
    ID_WORKER_STR(5); //ID_WORKER的字符串表示法 
}

  1. 重启测试,发现插入的id比上一条id多了1:

技术分享图片

update更新操作

    @Test 
    public void testUpdate(){
        User user = new User();  ?
        user.setId(1255894026599604227L);
        user.setName("yinrz2");
        user.setAge(21);
?
        int i = userMapper.updateById(user);
        System.out.println(i);
    }

技术分享图片

**注意:updateById传入的参数是一个对象!通过条件自动拼接动态sql 。要在主键上加入@TableId注解,或者主键名就叫id!!! **

delete删除操作

  1. 通过单个id删除
    @Test
    public void testDeleteById() {
        userMapper.deleteById(1255894026599604227L);
    }

技术分享图片

  1. 通过多个id批量删除
    @Test
    public void testDeleteBatchId() {
        userMapper.deleteBatchIds(Arrays.asList(1L, 2L));
    }

技术分享图片

  1. 通过map指定满足的条件,然后删除
    @Test
    public void testDeleteMap() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "Tom");
        userMapper.deleteByMap(map);
    }

技术分享图片

逻辑删除

物理删除 :从数据库中直接移除

逻辑删除 :再数据库中没有被移除,而是通过一个变量来让他失效! deleted = 0 变成 deleted = 1

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!

  1. 在数据库表中添加一个字段:deleted,int类型,默认值为0(0:未删除,1:删除)。
  2. 在实体类中增加对应字段,并添加@TableLogic注解
    @TableLogic
    private Integer deleted;
  1. 在MyBatisPlusConfig文件里添加Bean:
    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }
  1. 测试删除,发现走的是update方法而不是delete方法了:
@Test
public void testDeleteById() {
    userMapper.deleteById(4L);
}

技术分享图片

select查询操作

  1. 通过单个id查询
@Test
public void testSelectById() {
    User user = userMapper.selectById(4L);
    System.out.println(user);
}

技术分享图片

  1. 通过多个id查询
@Test
public void testSelectByBatchId() {
    List<User> users = userMapper.selectBatchIds(Arrays.asList(4,5));
    for (User user : users) {
        System.out.println(user);
    }
}

技术分享图片

  1. 通过map指定满足的条件,然后查询
@Test
public void testSelectByBatchIds() {
    HashMap<String, Object> map = new HashMap<>(); // 自定义要查询    
    map.put("name", "Sandy");
    map.put("age", 21);
    List<User> users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

技术分享图片

分页查询

  1. 在MyBatisPlusConfig中添加Bean:
@Bean
public PaginationInterceptor paginationInterceptor() {
    return  new PaginationInterceptor();
}
  1. 测试,使用Page对象,mapper使用selectPage方法,getRecords方法返回查询结果:
@Test
public void testPage() {
    //  参数一:当前页    //  参数二:页面大小       
    Page<User> page = new Page<>(1, 3);
    userMapper.selectPage(page, null);
    List<User> users = page.getRecords();
    for (User user:users){
        System.out.println(user);
    }
    System.out.println(page.getTotal());
}

技术分享图片

乐观锁

  • 乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做。

  • 当我们要对一个数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观锁

  • 乐观锁在修改时会带上version等于当前version值的条件,修改成功后会给version的值加1。加了乐观锁后,在并发环境下,多个人同时修改同一条数据时,只会有1个人修改成功,其他人修改失败。

如何实现:

  1. 在数据库表中添加version字段,int类型,默认值为1。
  2. entity类添加对应字段,并在该字段上添加注解:
    @Version
    private Integer version;
  1. 在MyBatisPlusConfig中,注册bean:
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
  1. 测试,发现线程2先修改然后将version的值+1,使得线程1修改不成功因为找不到对应version的值:
     @Test
    public void testOptimisticLocker() {
		// 线程1    
        User user = userMapper.selectById(8L);
        user.setName("yinrz3");
        // 线程2    
        User user2 = userMapper.selectById(8L);
        user2.setName("yinrz4");
        //线程2先更新
        userMapper.updateById(user2);    
        //线程1再更新
        userMapper.updateById(user); // 如果没有乐观锁就会成功更新
    }

技术分享图片

技术分享图片

自动填充

创建时间(gmt_create)、修改时间(gmt_modi?ed)几乎所有的表都要配置上,而且需要自动填充,我们不希望手动更新!

  1. 在数据库表中添加字段gmt_create与gmt_modi?ed,datetime类型,无默认值。
  2. 在实体类中添加对应字段,并添加注解:
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
  1. 编写一个handler来处理如何填充:
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    // 插入时的填充策略    
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    // 更新时的填充策略  
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}
  1. 插入一条数据测试,发现日期自动回填了:

技术分享图片

性能分析插件

我们在平时的开发中,会遇到一些慢sql,性能分析插件会帮助我们输出每条 SQL 语句及其执行时间 。

  1. 在MyBatisPlusConfig中配置Bean:
    @Bean
    @Profile({"dev","test"})// 设置 dev test 环境开启,保证我们的效率
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(500); //ms 设置sql执行的最大时间,如果超过了则不执行
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }
  1. 测试:

技术分享图片

? 如果超时:

技术分享图片

条件查询器Wrapper

allEq,eq,ne(不等于),gt(大于),ge(大于等于),lt,le,between,notBetween,like,notLike,likeLeft(百分号在左边),likeRight(百分号在右边),isNull,isNotNull,in,notIn,inSql(子查询),notInSql,groupBy,orderBy(默认,升序,小到大),orderByAsc(升序),orderByDesc(降序),having,or,and,nested,apply,last,exists,notExists。

@Test
public void testWrapper() {
    QueryWrapper<User> wrapper=new QueryWrapper<>();
    wrapper.eq("name","yinrz")           //name = yinrz
            .between("age",18,22)  //age BETWEEN 18 AND 22
            .like("name","a")       // email LIKE  %a%
            .notLike("email","b")   //email NOT LIKE  %b%
            .likeRight("email","c") //email LIKE c%
            .likeLeft("email","d")  //email LIKE %d
            .inSql("id","select id from user where id < 10") //id IN (select id from user where id < 10)
            .orderByDesc("id"); //ORDER BY id DESC
    List<User> users = userMapper.selectList(wrapper);
    for (User user :users){
        System.out.println(user);
    }
}

技术分享图片

代码自动生成器

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、 Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

 public static void main(String[] args) {
        //代码自动生成器
        AutoGenerator autoGenerator = new AutoGenerator();

        //1.全局配置
        GlobalConfig gc=new GlobalConfig();
        gc.setOutputDir(System.getProperty("user.dir")+"/src/main/java"); //文件输出路径
        gc.setAuthor("yinrz");  //作者名
        gc.setOpen(false);  //是否打开文件
        gc.setDateType(DateType.ONLY_DATE); //设置创建的日期
        gc.setFileOverride(false); //是否覆盖
        gc.setServiceName("%sService");  //去Service的I前缀
        gc.setIdType(IdType.ID_WORKER);  //主键填充策略
        gc.setSwagger2(true);			//是否加入Swagger注解
        autoGenerator.setGlobalConfig(gc);

        //2.配置数据源
        DataSourceConfig dsc=new DataSourceConfig();
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8");
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setDbType(DbType.MYSQL);
        autoGenerator.setDataSource(dsc);

        //3.配置包
        PackageConfig pc = new PackageConfig();
        //pc.setModuleName("xxx");  //模块名
        pc.setParent("com.yinrz");   //父包名
        pc.setEntity("entity");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");
        autoGenerator.setPackageInfo(pc);

        //4.配置策略
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user");      //数据库的表名
        strategy.setNaming(NamingStrategy.underline_to_camel);  //数据库表名驼峰命名
        strategy.setColumnNaming(NamingStrategy.underline_to_camel); //数据库字段驼峰命名
        strategy.setEntityLombokModel(true); //加lombok注解
        strategy.setLogicDeleteFieldName("deleted"); //逻辑删除的字段名
        //配置自动填充
        TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
        TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate);
        tableFills.add(gmtModified);
        strategy.setTableFillList(tableFills);
        strategy.setVersionFieldName("version"); //乐观锁的字段名
        strategy.setRestControllerStyle(true); //RestController注解
        strategy.setControllerMappingHyphenStyle(true); // 类似于localhost:8080/hello_id_2
        autoGenerator.setStrategy(strategy);

        //执行代码生成
        autoGenerator.execute();
    }

技术分享图片

MyBatis-Plus

原文:https://www.cnblogs.com/yinrz/p/12812407.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!