迎着风跑  

Mybatis-Plus 框架

#1. 写在前面的话

我个人不太喜欢使用 MyBatis-Plus 。原因在于:它只解决掉了一部分问题,而且在它所解决的问题的领域内,它还不是唯一方案。

简单来说就是这样:

  • 数据库操作的 “简单问题” ,MyBatis 解决;

  • 数据库操作的 “简单的复杂问题” ,MyBatis-Plus / Tk-Mapper / Example 等方案可以帮忙解决;

  • 数据库操作的 “复杂的复杂问题” ,还得回到 MyBatis 中用笨办法解决。

个人觉得有点 “食之无味,弃之可惜” 的感觉。

那么为什么 Mybatis-Plus 好像用的还蛮广泛?

  1. MyBatis 在国内的使用率远高于国外,而 MyBatis-Plus 又是国人做的,因此 MyBatis-Plus 在国人的 MyBatis 圈子中曝光度还是很高的,基本上仅次于 MyBatis 的分页插件 PageHelper 。所以,无论你用不用 Mybatis-Plus ,你肯定是听说过它的。

  2. 虽然 MyBatis-Plus 等一干方案仅仅只能简化 MyBatis 的一部分复杂操作,但是基于 “聊胜于无” 的考虑,能偷多少懒就偷多少懒,因此,这一批方案总还是有人会考虑去选一个用的,否则 “一点懒都不偷” 不符合人性。

  3. MyBatis-Plus 的出现和宣传比它的竞品们都要早,出于 “先发” 优势,在这一批方案中 “最出名” 的也就是 MyBatis-Plus 了。无论你考虑用哪一个,MyBatis-Plus 一定是你的备选项之一,它出现概率高,那么被选中的概率自然也就高了。

回到我个人的观点,相较于 MyBatis-Plus ,我更倾向于使用 Example 。原因在于:它是官方提出的解决方案,并且使用它没有引入任何额外的包。

TIP

对于包、方案的选择问题,我个人一贯的观点是:能用官方包,就不要使用第三方包;能用官方推荐第三方包,就不要使用其它第三方包。

#2. 入门

  • 引入 maven 依赖

    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.4.2</version>
    </dependency>
    
    Copied!

    如果你使用的是阿里云的 spring initializer ,你可以在直接去选择 myabtis-plus 。

  • 定义 PO 类,并标注注解

    @Data
    @TableName("department")
    public class Department {
    
        @TableId(value = "id", type = IdType.AUTO)
        private Long id;
    
        @TableField(value = "name", jdbcType = JdbcType.VARCHAR)
        private String name;
    
        @TableField(value = "location", jdbcType = JdbcType.VARCHAR)
        private String location;
    
    }
    
    Copied!
  • 定义 Mapper 接口,要求继承自特定父接口:

    public interface DepartmentDao extends BaseMapper<Department> {
    }
    
    Copied!

    因为我们的自定义接口继承了mybatis-plus 的接口,因此我们的接口中自然 “天生就有” 若干方法。

  • 配置 mybatis 包扫描,扫描 mapper 接口所在位置

    @SpringBootApplication
    @MapperScan(basePackages = "com.example.mybatisplusdemo.outlet.dao")
    public class MybatisPlusDemoApplication {
        ...
    }
    
    Copied!
  • 使用

    @Resource
    private DepartmentDao dao;
    
    @Test
    public void demo1() {
        Wrapper<Department> eq = new QueryWrapper<Department>().eq("id", 1L);
        System.out.println(dao.selectOne(eq));
    }
    
    Copied!

#3. Mapper CRUD 接口

Mapper CRUD 接口(opens new window)

除了基本的 CRUD 操作,mybatis-plus 带来的简便之处是简化了条件查询。

#4. 条件查询

按用户名和状态查询后台用户并按创建时间降序排列为例。SQL 实现如下:

SELECT *
FROM employee
WHERE department_id = 2
AND salary BETWEEN 500 AND 3000
ORDER BY salary DESC;
Copied!

在 mybatis-plus 中创建 Wrapper 对象,并调用对象的方法,例如,eq() 、between() 等方法来表达你所想的查询条件。这些条件之间是 AND 的关系:

@Data
@TableName("employee")
public class Employee {

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @TableField(value = "name", jdbcType = JdbcType.VARCHAR)
    private String name;

    @TableField(value = "job", jdbcType = JdbcType.VARCHAR)
    private String job;

    @TableField(value = "manager_id", jdbcType = JdbcType.BIGINT)
    private Long managerId;

    @TableField(value = "hire_date", jdbcType = JdbcType.DATE)
    private Date hireDate;
    @TableField(value = "salary", jdbcType = JdbcType.INTEGER)
    private Integer salary;

    @TableField(value = "commission", jdbcType = JdbcType.INTEGER)
    private Integer commissoin;

    @TableField(value = "department_id", jdbcType = JdbcType.BIGINT)
    private Long departmentId;
}
Copied!
Wrapper<Employee> wp1 = new QueryWrapper<Employee>()
        .eq("department_id", 2L)
        .between("salary", 500, 3000)
        .orderByDesc("salary");

employeeDao.selectList(wp1).forEach(System.out::println);
Copied!

#5. 逻辑条件的组合

逻辑条件的组合大体分为 2 种:

  • 单纯的 ...与...与... / ...或...或...

  • 与或 混用,由于  的优先级更高,因此可以改造成 (... and ...) or (... and ...) or ... 这样的统一形式。

#与与和或或

  • ...与...与... 情况:

    如上例所示,QueryWrapper 的链式调用中,所表达的逻辑关系就是 and 的关系。

  • ...或...或... 情况:

    这种关系中,在 Wrapper 对象的链式调用中穿插调用 or() 方法即可。or() 方法前后的条件就是或的关系。

    Wrapper<Employee> wp1 = new QueryWrapper<Employee>()
            .lt("salary", 1000)
            .or()
            .isNotNull("commission");
    
    employeeDao.selectList(wp1).forEach(System.out::println);
    
    Copied!

#与或混用

与或 混用的情况下,先要把你『心里』的 SQL 语句改造成通用形式:(... and ...) or (... and ...) or ... 。

Wrapper<Employee> wrapper = new QueryWrapper<Employee>()
        .eq("department_id", 2L)
        .lt("salary", 1500)
        .or()
        .eq("department_id", 3L)
        .gt("salary", 1300);

employeeDao.selectList(wrapper).forEach(System.out::println);
Copied!

#6. 条件删除

我们『心里』期望执行的 SQL 如下:

DELETE  FROM  department WHERE  name = 'test'; 
Copied!

使用 Wrapper 对应 Java 中的实现如下:

Wrapper<Department> wrapper = new QueryWrapper<Department>().eq("name", "test");
departmentDao.delete(wrapper);
Copied!

#7. 条件修改

我们『心里』期望执行的 SQL 如下:

update
    department
set name     = 'hello-new',
    location = 'world'
where 
    name = 'hello';
Copied!

使用 Wrapper 对应 Java 中的实现如下:

Department department = new Department(null, "hello-new", "world");
Wrapper<Department> wrapper = new QueryWrapper<Department>()
        .eq("name", "hello");

departmentDao.update(department, wrapper);
Copied!

注意,这里的 null 值表示保持原址不变。

posted on 2021-12-10 19:33  迎着风跑  阅读(550)  评论(0编辑  收藏  举报