MyBatis plus快速入门

MyBatis plus

简介

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

愿景

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

img

#特性

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

  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

#支持数据库

  • mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver

  • 达梦数据库 、 虚谷数据库 、 人大金仓数据库

#框架结构

framework

 

快速使用

在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:

@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {
​
    public static void main(String[] args) {
        SpringApplication.run(QuickStartApplication.class, args);
    }
​
}

编写实体类 User.java(此处使用了 Lombok 简化代码)

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

编写Mapper类 UserMapper.java

public interface UserMapper extends BaseMapper<User> {
​
}

测试查询,无条件

@RunWith(SpringRunner.class)
@SpringBootTest
public class PulsTest {
​
    @Autowired
    private UserMapper userMapper;
​
    @Test
    public void testSelect() {
        List<User> userList = userMapper.selectList(null);
        for (User user : userList) {
            System.err.println(user);
        }
    }

 

配置日志

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

CRUD扩展

插入

@Test
public void testInsert(){  
    User user=new User();    
    user.setName("军鹏");   
    user.setAge(20);    
    user.setEmail("1234@qq.com");    
    int insert = userMapper.insert(user);    
    System.err.println(insert);    
    System.err.println(user);
}

自增

@Data
public class User {
  @TableId(type = IdType.AUTO) //AUTO为自增,注意数据库也要设为自增
  private int id;
  private String name;
  private int age;
  private String email;
}

修改

@Test
public void testUpdata(){ 
    User user=new User();   
    user.setId(7);  
    user.setName("博洋");   
    user.setAge(24);    
    int i = userMapper.updateById(user);   //参数是实体类对象
    System.err.println(i+"::::"+user);
}

其他源码

public enum IdType {
    AUTO(0), //自增
    NONE(1), //未设置主键
    INPUT(2), //手动设置 一但设置,必须填写
    ASSIGN_ID(3),//默认的全局唯一id
    ASSIGN_UUID(4), //全球唯一id

删除

@Test
public void testdelete(){
    int i = userMapper.deleteById(1);
    System.err.println(i);
}

自动填充

创建时间,修改时间!这些操作都是自动化完成,不希望手动更新!

阿里巴巴开发手册:所有的数据库:gmt_create、gmt_modified几乎所有表都要配置上!而且需要自动化!

 

代码级别

在实体类属性上添加注解

  @TableField(fill = FieldFill.INSERT)
  private Date createTime;
  @TableField(fill = FieldFill.INSERT_UPDATE)
  private Date updataTime;

编写处理器来处理这个注解即可

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    //插入时的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        // 第一个为数据库插入时间字段,第二为当前时间
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updataTime",new Date(),metaObject);
    }
    //更新时的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.setFieldValByName("updataTime",new Date(),metaObject);
    }
}

测试观察时间即可!

乐观锁&悲观锁

乐观锁:顾名思义十分乐观,他总是认为不会出现问题,无论干什么都不会加锁

悲观锁:顾名思义十分悲观,它总是以为都会出现问题,无论干什么都会加锁

乐观锁需要数库加个version字段

实体类加上注解

@Version
private Integer version;

写一个配置类、

@MapperScan("com.ysl.mapper")
@EnableTransactionManagement
@Configuration
public class MyMybatisPlusConfig {
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}

测试

@Test
    public void testle(){
        User user = userMapper.selectById(10);
        user.setName("博洋c");
        user.setAge(23);
        userMapper.updateById(user);
    }

失败测试

    
@Test
    public void testle2(){
        User user = userMapper.selectById(10);
        user.setName("博洋aaaaa");
        user.setAge(23);
        User user2 = userMapper.selectById(10);
        user2.setName("博洋bbbbb");
        user2.setAge(23);
        userMapper.updateById(user); //如果没有乐观锁就会覆盖插队线程的值
    }

根据id或多个id查询

    
@Test
    public void testSelectById(){
        User user = userMapper.selectById(2);
        System.err.println(user);
​
        List<User> users = userMapper.selectBatchIds(Arrays.asList(2, 3, 4));
        users.forEach(System.out::println);
    }

根据map查询实现动态sql

  
 @Test
    public void testSelectMap(){
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("name","军鹏");
        map.put("age",20);
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }

分页

现在配置的类中配置beane

@MapperScan("com.ysl.mapper")
@EnableTransactionManagement
@Configuration
public class MyMybatisPlusConfig {
    //乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
​
    //分页插件
    @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;
    }
}

测试

    
//分页查询
    @Test
    public void testSelectPage(){
        //第一个参数:当前页
        //第二个参数:当前页大小
        Page<User> page = new Page<>(1,5);
        userMapper.selectPage(page, null);
        //获得数据
        page.getRecords().forEach(System.err::println);
    System.err.println(page.getCurrent()+"::"+page.getSize()+"::"+page.getTotal()+"::"+page.getPages());
    }

删除操作

根据id

  
 @Test
    public void testDelect(){
        //根据id删除单个
        userMapper.deleteById(10);
        //根据id删除多个
        userMapper.deleteBatchIds(Arrays.asList(9,8));
    }
    

根据map

 @Test
    public void testDelectByMap(){
        //根据map删除
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("id",7);
        map.put("name","b博洋");
        userMapper.deleteByMap(map);
    }

逻辑删除

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

逻辑删除:没有从数据库中移除,而是通过一个变量让它失效 deleted=0 == deleted=1

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

测试一下,数据库加入deleted字段默认为0

实体类属性上加注解

 //逻辑删除
  @TableLogic
  private int deleted;

配置yml文件

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag  #全局逻辑删除字段值 3.3.0开始支持,详情看下面。
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

测试删除

记录还在数据库但是deleted的值为1了

测试查询

数据库明明有值,就是查不到

 

查询的时候,MyBitas plus 会自动拼接上 deleted字段为条件

 

条件构造器

Wrapper

测试

  
 @Test
    public void testSelect() {
        //查询邮箱不为空,并且年龄大于15岁
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("email").ge("age",15);
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.err::println);
    }
    @Test
    public void testSelect3() {
        //查询年龄在20-30之间
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age",20,30);
        Integer user = userMapper.selectCount(wrapper);
        System.err.println(user);
    }
    @Test
    public void testSelect4() {
        //模糊查询,查名字不包含e的
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.notLike("name","e");
        List<Map<String, Object>> user = userMapper.selectMaps(wrapper);
        user.forEach(System.err::println);
    }
    @Test
    public void testSelect5() {
         //子查询
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.inSql("id","select id from user where id>3");
        List<Object> user = userMapper.selectObjs(wrapper);
        user.forEach(System.err::println);
    }
    @Test
    public void testSelect6() {
        //通过id排序
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.err::println);
    }

代码自动生成器

 

//代码自动生成器生成器
public class KuangCode {
    public static void main(String[] args) {
        //需要构建一个代码自动生成器对象
        AutoGenerator mpg = new AutoGenerator();
        //配置策略
        //1.全局配置
        GlobalConfig gc = new GlobalConfig();
        String property = System.getProperty("user.dir");
        gc.setOutputDir(property+"/src/main/java");
        gc.setAuthor(""); //作者
        gc.setOpen(false); //是否打开资源管理
        gc.setFileOverride(false); //是否覆盖
        gc.setServiceName("%sService"); //去掉Service的I前缀
        gc.setIdType(IdType.ID_WORKER);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);
​
        //2.设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("1234");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);
​
        //3.包的配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName("blog");
        pc.setParent("com.ysl");
        pc.setEntity("pojo");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");
        mpg.setPackageInfo(pc);
​
        //4.策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("zby");
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);//自动设置Lombok
        strategy.setLogicDeleteFieldName("deleted");
        //自动填充配置  create_time   updata_time
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill updataTime = new TableFill("updata_time", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(createTime);
        tableFills.add(updataTime);
        strategy.setTableFillList(tableFills);
        //乐观锁
        strategy.setVersionFieldName("version");
​
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);//localhost:8080/hello_id_2
        mpg.setStrategy(strategy);
        mpg.execute();
​
    }
}
 
原文地址:https://www.cnblogs.com/yslss/p/12603430.html