本章目录
- AR模式
- 主键策略
- 基本配置
1. AR模式
Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录,属于动态模型。而Java作为准静态语言,对于 ActiveRecord 往往只能感叹其优雅,所以 MP 也在 AR 道路上进行了一定的探索,才有了现在的功能Java也能实现AR模式。简而言之,就是直接用实体类对数据库进行CRUD操作,接下来看具体代码:
要实现AR模式需要两个前提:一是实体类继承Model抽象类,二是定义实体类对应的mapper接口继承BaseMapper。
entity实体类
@Data
@TableName("sys_member")
public class MemberAR extends Model<MemberAR> {
@TableId
private Long id;
private String name;
private String password;
private Integer state;
private Long superId;
private LocalDateTime createTime;
}
注:实体类继承Model类
mapper类
public interface MemberARMapper extends BaseMapper<MemberAR> {
}
注:虽然AR模式用不到该接口,但是一定要定义,否则使用AR时会报空指针异常。
AR使用
(1).AR插入操作
@RequestMapping("/ar_insert")
public Result insert() {
MemberAR memberAR = new MemberAR();
memberAR.setId(10L);
memberAR.setName("第时");
memberAR.setPassword("12345");
memberAR.setState(2);
memberAR.setSuperId(1L);
memberAR.setCreateTime(LocalDateTime.now());
boolean insert = memberAR.insert();
System.out.println(insert);
return ResultUtil.success(insert);
}
注:可以看到我们并不需要注入mapper接口,不过正如刚才所说,不使用但还是要定义,否则会报错。AR操作是通过对象本身调用相关方法,比如要insert一个memberAR,那就用这个memberAR调用insert方法即可。返回值为布尔类型,由上图可看到返回了true,是指操作成功。
(2).AR删除操作
@RequestMapping("/ar_delete")
public Result deleteAR() {
MemberAR memberAR = new MemberAR();
//删除数据库中不存在的数据也是返回true
//1.根据id删除
//boolean deleteById = memberAR.deleteById(10L);
//或者这样
//memberAR.setId(10L);
//boolean deleteById = memberAR.deleteById();
//2.根据条件删除
boolean delete = memberAR.delete(new QueryWrapper<MemberAR>().like("name", "第"));
return ResultUtil.success(delete);
}
注:这里介绍了两个删除方法,代码中已有注释说明。需要注意的是,在MP中删除数据库中不存在的数据逻辑上也算删除,所以结果也是true。
(3).AR更新操作
@RequestMapping("/ar_update")
public Result updateAR() {
MemberAR memberAR = new MemberAR();
memberAR.setId(10L);
memberAR.setCreateTime(LocalDateTime.now());
boolean updateById = memberAR.updateById();
return ResultUtil.success(updateById);
}
注:memberAR调用updateById方法,将id为10的用户进行时间更新。
// 这里演示另一个方法insertOrUpdate
@RequestMapping("/ar_insertOrUpdate")
public Result insertOrUpdateAR() {
MemberAR memberAR = new MemberAR();
//1.插入操作
//memberAR.setName("张强");
//memberAR.setPassword("12345");
//boolean insertOrUpdate = memberAR.insertOrUpdate();
//2.更新操作
memberAR.setId(10L);
memberAR.setCreateTime(LocalDateTime.now());
boolean insertOrUpdate = memberAR.insertOrUpdate();
return ResultUtil.success(insertOrUpdate);
}
注:当实体类对象中没有设置id时,memberAR调用insertOrUpdate方法为插入数据;当实体类对象中设置id时,如上图会先执行select操作,查询到该id对应的数据时则再使用update操作,查询不到该id对应的数据时则再使用insert操作。
(4).AR查询操作
@RequestMapping("/ar_select")
public Result selectAR() {
MemberAR memberAR = new MemberAR();
//1.根据id查询
//MemberAR ar = memberAR.selectById(10);
// 或者这样
//memberAR.setId(10L);
//MemberAR ar = memberAR.selectById();
//2.查询所有
//List<MemberAR> ars = memberAR.selectAll();
//3.根据条件查询
//List<MemberAR> ars = memberAR.selectList(new QueryWrapper<MemberAR>().like("name", "第"));
//4.查询符合条件的总数
int count = memberAR.selectCount(new QueryWrapper<MemberAR>().eq("state", 1));
return ResultUtil.success(count);
}
注:上面的代码涉及到了四个不同的查询操作,其实用法与MP的BaseMapper提供的方法的用法差不多,只不过这里是实体对象调用。
(5).AR分页操作
@RequestMapping("/ar_page")
public Result pageAR() {
MemberAR memberAR = new MemberAR();
Page<MemberAR> selectPage = memberAR.selectPage(new Page<>(1, 4),
new QueryWrapper<MemberAR>().eq("state", 1));
List<MemberAR> selectPageRecords = selectPage.getRecords();
return ResultUtil.success(selectPageRecords);
}
注:使用MP中的selectPage方法,传入page参数和where条件构造器,以每页4条数据查询出第1页的数据集合。该方法会先执行一条查询总记录数,再执行limit分页查询,如果不需要查询总记录数,可在page中设置第三个参数new Page<>(1, 4, false)。
2. 主键策略
MP中提供了多种主键策略,根据应用场景不同可对不同实体分别使用各自的主键策略,也可全局统一策略,接下来看具体代码:
@Data
@TableName("sys_member")
public class Member {
/**
* //1.设置主键自增,数据库同样要进行主键自增设置
* @TableId(type = IdType.AUTO)
*
* //2.数据库不设置主键自增,实体类设置id则使用设置的id进行插入,实体类不设置id则使用默认的雪花算法
* @TableId(type = IdType.NONE)
*
* //3.这个就是雪花算法(默认)
* @TableId(type = IdType.ID_WORKER)
*
* //4.这个雪花算法要求id是String类型的
* @TableId(type = IdType.ID_WORKER_STR)
*
* //5.UUID要求id为String类型
* @TableId(type = IdType.UUID)
*
* 注:3、4、5 这三种主键策略只有当插入对象ID为空,才自动填充!
*/
@TableId(type = IdType.AUTO)
private Long id;
//@TableField(condition = SqlCondition.LIKE)
private String name;
private String password;
private Integer state;
private Long superId;
private LocalDateTime createTime;
}
在实体类中id属性上加上相应注解即可实现局部策略,另外全局策略需在application.yml中配置,需要注意的是局部策略大于全局策略,配置如下:
mybatis-plus:
# MP设置全局id策略为uuid,局部设置id策略在实体类对象的id属性上设置(局部策略 大于 全局策略)
global-config:
db-config:
id-type: uuid
注:MP提供的每种主键策略我在代码中已经加上注释,对于不同的场景需要使用不同的策略,例如需要id无规则的时候就建议使用雪花算法和UUID。
3. 基本配置
(1).基本配置
mybatis-plus:
# mybatis的自定义配置
config-location: classpath:mybatis-config.xml
注:在application.yml文件中配置如上数据,resources目录下创建mybatis-config.xml用来添加自己需要的mybatis配置。
mybatis-plus:
# myBaits别名包扫描路径配置
type-aliases-package: com.ethan.entity
<!-- 没有配置myBaits别名包扫描路径 -->
<mapper namespace="com.ethan.dao.MemberMapper">
<select id="selectAllMembers" resultType="com.ethan.entity.Member">
select * from sys_member ${ew.customSqlSegment}
</select>
<select id="selectMemberPage" resultType="com.ethan.entity.Member">
select * from sys_member ${ew.customSqlSegment}
</select>
</mapper>
<!-- 已配置myBaits别名包扫描路径 -->
<mapper namespace="com.ethan.dao.MemberMapper">
<select id="selectAllMembers" resultType="Member">
select * from sys_member ${ew.customSqlSegment}
</select>
<select id="selectMemberPage" resultType="Member">
select * from sys_member ${ew.customSqlSegment}
</select>
</mapper>
注:myBaits别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在Mapper对应的XML文件中可以直接使用类名,而不用使用全限定的类名。(即XML中调用的时候不用包含包名)
(2).进阶配置
mybatis-plus:
configuration:
# 是否开启自动驼峰命名规则映射,MP默认是开启的
map-underscore-to-camel-case: true
注:例如数据库列名 A_COLUMN(下划线命名) 到 Java 属性名 aColumn(驼峰命名) 的类似映射。如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名。
(3).DB策略配置
mybatis-plus:
global-config:
db-config:
# 字段验证策略配置
insert-strategy: not_null
update-strategy: not_null
select-strategy: not_null
注:全局策略中这三个字段验证策略约定了如何产出注入的sql,涉及insert、update以及wrapper内部的entity属性生成的where条件,三个字段验证策略都有not_null、not_empty、ignored等属性,默认是not_null,及当字段没有设置值时不注入sql。
@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)
private String name;
注:也可以配置局部策略,局部策略优先于全局策略。当我们某个实体类中的某个属性不使用全局策略时,可单独配置局部策略,即在实体类属性上加上如上注解,FieldStrategy的属性跟全局策略中的属性一样。
mybatis-plus:
global-config:
db-config:
# 表名前缀配置
table-prefix: sys_
注:表名前缀配置,当我们全库表名前缀一致时可使用该配置进行全局配置表名前缀,这样当我们编写实体类时就不需要像之前一样每个实体类上都加上@TableName("sys_xx")注解,只需实体类名与xx一致即可自动匹配对应数据库表。