mybatis_plus

Mybatis Plus是Mybatis 增强版工具

  1. 已经封装好一些crud方法,不需再写xml,直接调用这些方法即可。

如果集成mybatis-plus,就把mybatis、mybatis-spring去掉,避免冲突

pom.xml

1
2
3
4
5
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>Latest Version</version>
</dependency>

entity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
@TableName(value = "tb_employee") //指定表名
public class Employee {
//value与数据库主键列名一致,若实体类属性名与表主键列名一致可省略value
@TableId(value = "id",type = IdType.AUTO)//指定自增策略
private Integer id;

//若没有开启驼峰命名,或者表中列名不符合驼峰规则,可通过该注解指定数据库表中的列名,exist标明数据表中有没有对应列
@TableField(value = "last_name",exist = true)
private String lastName;

// 其他不需要特别处理
private String email;
private Integer gender;
private Integer age;
}

mapper

不需要写xml映射,不需要定义任何接口方法。

1
2
public interface EmplopyeeDao extends BaseMapper<Employee> {
}

crud操作

  1. 大部分单表 CRUD 操作,仅仅需要继承一个 BaseMapper 即可实现。
  2. 复杂CRUD操作,使用条件构造器: EntityWrapperCondition

基本crud操作

1
2
3
//insert 可以拿到insert之后的记录id
Employee employee = new Employee();
int emplopyeeDao.insert(employee);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// deleteById 根据id删除
emplopyeeDao.deleteById(1);

// deleteBatchIds 根据多个id批量删除
List<Integer> idList = new ArrayList<>();
idList.add(1);
idList.add(2);
emplopyeeDao.deleteBatchIds(idList);

// deleteByMap 根据自定义条件删除,返回值是Integer类型,表示影响的行数。
Map<String,Object> columnMap = new HashMap<>();
columnMap.put("gender",0);
columnMap.put("age",18);
emplopyeeDao.deleteByMap(columnMap);

// 根据 entity 条件,删除记录(条件构造器)
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
1
2
3
4
5
6
7
8
//updateById  根据id进行更新,只更新传值的属性,没有传值的属性就不会更新
emplopyeeDao.updateById(employee);

//updateAllColumnById 根据id进行更新,默认更新所有属性,没传值的属性就更新为null
//emplopyeeDao.updateAllColumnById(employee);

//update 根据 whereEntity 条件,更新记录(条件构造器)
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// selectById 只根据一个id,查询一条
Employee employee = emplopyeeDao.selectById(1);

// selectBatchIds 根据多个id,批量查询
List<Integer> idList = new ArrayList<>();
idList.add(1);
idList.add(2);
idList.add(3);
List<Employee> employees = emplopyeeDao.selectBatchIds(idList);

// selectOne 根据自定义条件,查询一条记录(若符合条件的记录有多条,不能使用这个方法,会直接报错!)
emplopyeeDao.selectOne(employeeCondition);

// selectByMap 根据自定义条件,查询多条记录(查询条件用map集合封装)
Map<String,Object> columnMap = new HashMap<>();
columnMap.put("last_name","tom");//严格写表中的列名(而非实体类)
columnMap.put("gender","1");
List<Employee> employees = emplopyeeDao.selectByMap(columnMap);

// selectList 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// selectMaps 根据 Wrapper 条件,查询全部记录,
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// selectObjs 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);


// selectPage 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

条件构造器crud

使用MyBatis : 需要在 SQL 映射文件中编写带条件查询的 SQL,并用PageHelper 插件完成分页. 实现以上一个简单的需求,往往需要我们做很多重复单调的工作。
使用MybatisPlus: 依旧不用编写 SQL 语句,MP 提供了功能强大的条件构造器。

条件构造器

  1. Condition:调create方法创建出来,Condition.create()
  2. EntityWrapper:是new出来的,new EntityWrapper<>()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 分页查询 selectPage
List<Employee> employees = emplopyeeDao.selectPage(new Page<Employee>(1,3),
new EntityWrapper<Employee>()
.between("age",18,50)
.eq("gender",0)
.eq("last_name","tom") // 注意column是数据表对应的字段,而非实体类属性字段。
);

List<Employee> employees = emplopyeeDao.selectPage(new Page<Employee>(1,3),
Condition.create()
.between("age",18,50)
.eq("gender",0)
.eq("last_name","tom") // 注意column是数据表对应的字段,而非实体类属性字段。
);

// null,表示没有查询条件
List<Employee> employees = emplopyeeDao.selectPage(new Page<>(1,2),null);
System.out.println(employees);

// 批量查询 selectList, like
List<Employee> employees = emplopyeeDao.selectList(
new EntityWrapper<Employee>()
.eq("gender",0)
.like("last_name","老师") // like方法模糊查询
//.or()//和or new 区别不大
.orNew()
.like("email","a")
);

// 批量查询 selectList, last
List<Employee> employees = emplopyeeDao.selectList(
new EntityWrapper<Employee>()
.eq("gender",0)
.orderBy("age")//升序,orderByDesc是降序
.last("desc limit 1,3")//在sql语句后面直接追加last里面的内容(改为降序,同时分页)
);
1
2
3
4
5
6
7
8
9
// update  根据条件EntityWrapper,只更新明文设置的属性
Employee employee = new Employee();
employee.setGender(0);

emplopyeeDao.update(employee,
new EntityWrapper<Employee>()
.eq("last_name","tom")
.eq("age",25)
);
1
2
3
4
5
6
// delete 把符合条件的全部删除
emplopyeeDao.delete(
new EntityWrapper<Employee>()
.eq("last_name","tom")
.eq("age",16)
);

ActiveRecord

AR是一种领域模型。领域模型的特点是一个模型类对应关系型数据库中的一个表,模型类的一个实例对应表中的一行记录。

所谓AR操作,是通过对象本身调用相关方法,比如要insert一个user,那就用这个user调用insert方法即可user.insert()

MPlus 实现了只需要让实体类继承 Model 类且实现主键指定方法,即可使用AR。

步骤1:让实体类继承 Model 类,并实现指定主键的方法

1
2
3
4
5
6
7
8
9
10
11
12
@Data
public class User extends Model<User> {
private Integer id;
private String name;
private Integer age;
private Integer gender;
//重写这个方法,return当前类的主键
@Override
protected Serializable pkVal() {
return id;
}
}

步骤2:虽然AR模式用不到该接口,但是一定要定义,否则使用AR时会报空指针异常。

1
2
public interface UserDao extends BaseMapper<User> {
}

步骤3:

可看到,不需要引入mapper接口(UserDao),就可以直接使用insert方法!不过,虽然不需要引入,但还是要定义,否则会报错。

user.insert();就是AR的写法,可以看到返回值为布尔类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
User user = new User();
user.setAge(22);
user.setGender(1);
boolean result = user.insert();

User user = new User();
user.setId(1);
user.setName("刘亦菲");
boolean result = user.updateById();

int result = user.selectCount(new EntityWrapper<User>().eq("gender",1));

boolean result = user.delete(new EntityWrapper<User>().like("name","玲"));

特殊用法

逻辑删除

1
2
3
4
@TableLogic //标记逻辑删除属性
private Integer logicFlag;

则执行delete语句时候,并不会真的删除,而是把被 @TableLogic修饰的字段,修改一下标志位

填充默认值

1
2
3
4
5
@TableField(fill = FieldFill.INSERT, update = "now()") // 插入时,填充now()
override var createdTime: Date = Date()

@TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充
private String name;

枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 调用
private GradeEnum grade;
private AgeEnum age;

// 定义
@Getter
public enum GradeEnum {

PRIMARY(1, "小学"),
SECONDORY(2, "中学"),
HIGH(3, "高中");

GradeEnum(int code, String descp) {
this.code = code;
this.descp = descp;
}

@EnumValue
private final int code;

private final String descp;

}
// 定义方式2
public enum AgeEnum implements IEnum<Integer> {
ONE(1, "一岁"),
TWO(2, "二岁"),
THREE(3, "三岁");

private int value;
private String desc;

@Override
public Integer getValue() {
return this.value;
}
}

枚举序列化(翻倍入库)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// springboot + jackson为例
// 定义
@Getter
public enum GradeEnum {

PRIMARY(1, "小学"),
SECONDORY(2, "中学"),
HIGH(3, "高中");

GradeEnum(int code, String descp) {
this.code = code;
this.descp = descp;
}

@EnumValue
@JsonValue //标记响应json值
private final int code;

private final String descp;

}

字段类型处理器

类型处理器:

  1. 用于 JavaType 与 JdbcType 之间的转换
  2. 用于 PreparedStatement 设置参数值和从 ResultSet 或 CallableStatement 中取出一个值。

    mybaits-plus 内置常用类型处理器,通过TableField注解快速注入到 mybatis 容器中。

插件

分页插件:

BaseMapper的selectPage方法和AR提供的selectPage方法都不是物理分页,需要配置分页插件后才是物理分页

1
2
3
4
5
//配置了分页插件后,还是和以前一样的使用selectpage方法,
//但是现在就是真正的物理分页了,sql语句中有limit了
Page<Employee> page = new Page<>(1, 2);
List<Employee> employeeList = emplopyeeDao.selectPage(page, null);
page.setRecords(employeeList);

数据库框架:Mybatis Plus > Mybatis

代码生成器:Mybatis Plus Generator > Mybatis Generator

参考

官网

-------------Keep It Simple Stupid-------------
0%