美文网首页
简单之美 MyBatis Plus

简单之美 MyBatis Plus

作者: 秋的蓝 | 来源:发表于2018-11-02 23:03 被阅读0次

    前言

    项目开发一直使用MyBatis , 简单,方便,容易上手,调优比其他的ORM框架容易的多。最近一次偶然的搜索,发现了MyBatis Plus, 试用之后,真是太爽了。MyBatis Plus是攻城狮的福利,几乎不用编码就可以完成单表的CRUD操作。使用心得做个记录。

    一、准备环境

    IDE编辑器:IntelliJ IDEA 2018.2.4(Ultimate Edition)
    数据库:MySQL 5.7
    框架:MyBatis Plus 3.05 , Spring Boot 2.0.6
    管理工具:Maven 3.3.9
    JDK:jdk1.8或以上

    1. IDEA设置

    idea是java开发的利器,我个人的常用设置有这么几项:

    1) 设置自动导入包
    自动导入包
    2) 设置提示快捷键

    idea默认的代码提示是ctrl + 空格,常和输入法冲突,可以改为 alt + /,特别是从Eclipse转过来的同学,alt + / 比较顺手。


    设置代码提示快捷键 alt + /
    3) 设置多Tab标签

    idea默认代码区的Tab标签是单行显示,多文件时不方便。


    代码区多Tab显示
    4) 设置提示不区分大小写

    idea默认是按首字母大小写匹配,进行代码提示, 例如输入FileReader,必须F是大写才有提示, 设置完成后 f 也可以有提示。


    代码提示不区分大小写
    5) 设置的包显示风格
    设置包的扁平风格

    2. 安装其他软件

    安装jdk1.8 , mysql 5.7 ,maven3以上版本

    二、初识 MyBatis Plus

    官网:MyBatis Plus
    MyBatis Plus 简称MP, 是MyBatis的增强,不做改变,只做增强。简单而又强大。
    MP是一只带着蓝色面罩的小鸟。

    logo.png

    1. 功能特性

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

    以上特性大多都是项目开发中必用的功能。

    2. 开始上手

    MP主页有示例,按照例子步骤就可以快速搭建MP项目。

    • 准备表 student
      主键是id字段, auto increment
      student.png
    • 创建Spring Boot项目
      建议使用 Spring Initializr,依赖项选择MySQL
      创建springboot项目

    依赖MySQL
    • pom.xml
      工程属性
     <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
     </properties>
    

    parent依赖项

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.6.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    

    SpringBoot 依赖项

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

    MyBatis Plus依赖项

       <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.0.5</version>
       </dependency>
    

    MySQL 依赖项

      <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
      </dependency>
    
    • 配置数据库信息
      编辑resource/application.yml文件,使用默认的application.properties文件也是可以的,两种类型的文件作用一样,语法格式有区别。
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=UTF-8
        username: test
        password: 123456
    
    • 创建entity类
      创建Student类,属性名和列名相同
    public class Student {
        //指定主键为 自动增长(mysql的 auto increment)
        @TableId(value = "id",type = IdType.AUTO)
        private Integer id;
        private String name;
        private Integer age;
        private String email;
        private Integer status;
        private Date createtime;
        // set | get
    
    • 创建Mapper接口
    public interface StudentMapper extends BaseMapper<Student> {
       //无需任何内容
    }
    
    • 测试insert
      在test/java/ 目下创建测试类,使用@Test修饰测试方法
    @SuppressWarnings("all")
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class MPTest {
        @Autowired
        private StudentMapper studentMapper;
    
        @Test
        public void testInsertStudent(){
            Student student = new Student();
            student.setName("李名");
            student.setAge(20);
            student.setEmail("liming@163.com");
            student.setStatus(1);
            student.setCreatetime( new Date());
            int rows = studentMapper.insert(student);
            System.out.println("insert 结果:"+rows);
        }
    
    }
    

    三、实体属性名和列名相同

    上面“2 开始上手”,实体类属性名和表的列名是相同的,使用MP无需设置,就可以完成CRUD, 在这部分继续实行其他的单表操作。

    1. 增加数据

    同“2 开始上手”中的测试部分的代码,首先创建实体对象, 给属性赋值,调用studentMapper的insert(),参数是实体类对象, insert()返回值是数据库插入成功的行数。整数值。

        //添加记录,并获取新记录的注解
        @Test
        public void testInsertStudent() {
            Student student = new Student();
            student.setName("周新");
            student.setAge(20);
            student.setEmail("liming@163.com");
            student.setStatus(1);
            student.setCreatetime(new Date());
            int rows = studentMapper.insert(student);
            // 主键是id,获取新添加记录的id,使用对象的getId()
            int newId = student.getId();
            System.out.println("insert 结果:" + rows + "|对象的id:"+newId);
        }
    

    输出:insert 结果:1|对象的id:8 , id是你插入数据主键和我的不同。

    2.修改数据

        //根据主键修改对象
        @Test
        public void testUpdateStudent(){
            Student student = new Student();
            student.setId(8);
            student.setName("新的名字");
            student.setAge(30);
            //根据主键修改对象, 对象null的属性,不进行修改
            int rows = studentMapper.updateById(student);
        }
    

    首先给要修改的属性赋值,null的属性,不会参与修改。update set 列名=值不会出现null的字段;条件部分是 where id= 8;
    注意:MP判断是否修改字段是判断属性的null,最好实体类Student的属性都是引用类型, 包括Integer age , 这样不给age赋值,就不会更新age字段。如果实体类定义 int age 。

        //根据主键修改对象
        @Test
        public void testUpdateStudent(){
            Student student = new Student();
            student.setId(8);
            student.setName("新的名字");
            //student.setAge(30);
            //根据主键修改对象, 对象null的属性,不进行修改
            int rows = studentMapper.updateById(student);
        }
    

    MP的执行sql: UPDATE student SET name=?, age=? WHERE id=?
    修改结果是 age 是 0 , 因为Student属性 int age ,这样定义int类型默认初值是 0 。

    updateById()是根据主键作为添加更新,还可以根据其他条件更新,例如update(实体对象, Wrapper), Wrapper的使用后面会说到。

    3. 删除数据
    BaseMapper中删除方法

     deleteBatchIds(Collection); 参数是主键的集合,删除多条数据
     delete(Wrapper); 根据Wrapper对象的条件,删除数据
     deleteById(主键id);根据单一主键,删除数据
     deleteByMap(Map<String,Object>); 使用Map作为条件删除数据
    

        //删除数据
        @Test
        public void testDeleteStudent(){
            // sql : DELETE FROM student WHERE id=? 
            int rows = studentMapper.deleteById(2);
            System.out.println("deleteById结果:"+rows);
        }
    

    注:deleteById(), 参数是主键值, 删除条件是 where id = 2


        @Test
        public void testDeleteStudent2(){
           Map<String,Object> condition = new HashMap<>();
           condition.put("name","周新");
           condition.put("age",20);
           int rows = studentMapper.deleteByMap(condition);
           System.out.println("deleteByMap 结果:"+rows);
        }
    

    注:创建Map, 添加条件数据。Map的key是字段名,value是字段的值。调用deleteByMap(); 传入Map对象。 返回值成功删除的行数。


        @Test
        public void testDeleteStudent3(){
            //DELETE FROM student WHERE name = ? OR age > ? 
            QueryWrapper<Student> wrapper = new QueryWrapper<>();
            wrapper.eq("name", "周新")
                    .or()
                    .gt("age", 20);
            int rows = studentMapper.delete(wrapper);
            System.out.println("delete(wrapper) 结果:"+rows);
        }
    

    注:Wrapper是抽象类,QueryWrapper是他的子类, 用来封装条件字段和字段值。 eq()表示等于=, or() 是字段之间用 or 连接, gt()是大于。这些只是Wrapper中的几个方法, 参数是字段名,不是属性名。

    4. 查询数据
    BaseMapper的多个查询方法

      selectBatchIds(Collection); 查询集合中多个主键值数据
      selectByMap(Map<String,Object>); 根据Map条件查询
      selectList(Wrapper); 使用Wrapper对象作为查询条件
      selectById(id); 根据主键值查询
      selectPage(IPage, Wrapper); 根据Wrapper条件并进行分页
      selectCount(Wrapper); 统一记录数量
      selectOne(Wrapper); 查询结果是一个对象
    

    使用selectById , selectOne查询数据, 其他查询方法后面有单独的章节,独立讲查询的各种使用方式。

        @Test
        public void testSelectStudent(){
            // SELECT id,name,age,email,status,createtime FROM student WHERE id=?
            Student student = studentMapper.selectById(8);
            System.out.println("根据id查询结果:"+student);
        }
    

        @Test
        public void testSelectStudent2(){
            QueryWrapper<Student> condition = new QueryWrapper<>();
            condition.eq("name","李名");
            //SELECT id,name,age,email,status,createtime FROM student WHERE name = ?
            Student student = studentMapper.selectOne(condition);
            System.out.println("selectOne查询结果:"+student);
        }
    

    注:先创建Wrapper对象,添加查询条件, 调用selectOne()方法。 selectOne()的查询结果必须小于或等于一条记录,MP内部是调用的MyBatis的selectOne()方法,多于一个记录,系统会报错,错误提示如下:

    org.apache.ibatis.exceptions.TooManyResultsException

    相关文章

      网友评论

          本文标题:简单之美 MyBatis Plus

          本文链接:https://www.haomeiwen.com/subject/mcnatqtx.html