SpringBoot - MyBatis-Plus使用详解12(使用ActiveRecord模式进行增删改查)
十二、使用 ActiveRecord 模式操作数据库
1,ActiveRecord 模式介绍
- ActiveRecord(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。
- ActiveRecord 一直广受动态语言( PHP 、 Ruby 等)的喜爱,而 Java 作为准静态语言,对于 ActiveRecord 往往只能感叹其优雅。
- 不过 MyBatis-Plus 也在 AR 道路上进行了一定的探索,仅仅需要让实体类继承 Model 类且实现主键指定方法,即可开启 AR 之旅。
2,准备工作
(1)假设我们有如下用户信息表 user_info:

(2)首先创建对应的实体类 UserInfo:
注意:与之前不同的是,实体类需要继承 Model 类,并重写 pkVal 方法。
@Data public class UserInfo extends Model<UserInfo> { private Integer id; private String userName; private String passWord; private Integer age; //重写这个方法,return当前类的主键 @Override protected Serializable pkVal() { return id; } }
(3)接着同样创建 UserInfoMapper 接口,并继承 BaseMapper 接口。
提示:虽然 AR 模式用不到该接口,但是一定要定义,否则使用 AR 时会报空指针异常。
public interface UserInfoMapper extends BaseMapper<UserInfo> { }
3,新增数据
AR 操作是通过对象本身调用相关方法,比如要 insert 一个 user,那就用这个 user 调用 insert 方法即可。UserInfo user = new UserInfo(); user.setUserName("hangge"); user.setPassWord("!0001"); user.setAge(100); //AR插入操作,返回执行是否成功 Boolean success = user.insert();
4,修改数据
(1)使用实体对象的 updateById 方法可以根据主键 ID 更新对应的数据:UserInfo user = new UserInfo(); user.setId(1); user.setUserName("hangge"); user.setPassWord("!0001"); user.setAge(100); //根据id修改数据,返回执行是否成功 Boolean success = user.updateById();
(1)数据更新相关的构造器(UpdateWrapper、LambdaUpdateWrapper、LambdaUpdateChainWrapper)使用方法类似于查询构造器(QueryWrapper、LambdaQueryWrapper、LambdaQueryChainWrapper),不同的是它增加了如下两个方法:
- set:设置数据库字段值
- setSql:设置 set 部分的 sql
// 查询条件:名字中包含'ha'并且年龄小于40 LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.like(UserInfo::getUserName,"ha").lt(UserInfo::getAge,40); // 将满足条件的记录密码都设置为8888 UserInfo user = new UserInfo(); user.setPassWord("8888"); //修改数据,返回执行是否成功 Boolean success = user.update(updateWrapper);
- 我们也可以通过 updateWrapper 的 set 方法直接设置字段值,比如下面除了将密码设置为 8888 外,还将年龄设置为 null:
// 查询条件:名字中包含'ha'并且年龄小于40 LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.like(UserInfo::getUserName,"ha").lt(UserInfo::getAge,40) .set(UserInfo::getPassWord, "8888") .set(UserInfo::getAge, null); // 修改数据,返回执行是否成功 Boolean success = new UserInfo().update(updateWrapper); /*********** 二者可以结合使用的,下面效果等效于上面的 ****************/ // 查询条件:名字中包含'ha'并且年龄小于40 LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.like(UserInfo::getUserName,"ha").lt(UserInfo::getAge,40) .set(UserInfo::getAge, null); // 将满足条件的记录密码都设置为8888 UserInfo user = new UserInfo(); user.setPassWord("8888"); // 修改数据,返回执行是否成功 Boolean success = user.update(updateWrapper);
- 而也通过 updateWrapper 的 setSql 方法可以直接设置 set 部分的 sql,下面的效果同上面是一样的:
// 查询条件:名字中包含'ha'并且年龄小于40 LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.like(UserInfo::getUserName,"ha").lt(UserInfo::getAge,40) .setSql("pass_word = '8888'") .setSql("age = null"); // 修改改据,返回执行是否成功 Boolean success = new UserInfo().update(updateWrapper); /*********** 二者可以结合使用的,下面效果等效于上面的 ****************/ // 查询条件:名字中包含'ha'并且年龄小于40 LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.like(UserInfo::getUserName,"ha").lt(UserInfo::getAge,40) .setSql("age = null"); // 将满足条件的记录密码都设置为8888 UserInfo user = new UserInfo(); user.setPassWord("8888"); // 修改改据,返回执行是否成功 Boolean success = user.update(updateWrapper);
5,新增或修改数据
调用实体对象的 insertOrUpdate 会先判断实体类是否包含主键 ID,如果有的话则执行更新操作,没有的话则执行新增操作:UserInfo user1 = new UserInfo(); user1.setId(1); user1.setUserName("hangge"); user1.setAge(100); // 由于user1设置了主键id,则执行更新操作 user1.insertOrUpdate(); UserInfo user2 = new UserInfo(); user2.setUserName("hangge"); user2.setAge(100); // 由于user2没有设置主键id,则执行新增操作 user2.insertOrUpdate();
6,删除数据
(1)调用对象的 deleteById 方法可以根据 id 删除一条记录:
UserInfo user = new UserInfo(); user.setId(23); // 删除数据,返回执行是否成功 Boolean success = user.deleteById(); /****** 下面代码功能等效上面代码 ********/ Boolean success = new UserInfo().deleteById(23);
(2)调用对象的 delete 方法使用查询构造器删除记录:
关于查询条件构造器(QueryWrapper、LambdaQueryWrapper)的详细用法可以参考我之前写的文章:
// 查询条件:名字中包含'ha'并且年龄小于40 LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.like(UserInfo::getUserName,"ha").lt(UserInfo::getAge,40); // 删除数据,返回执行是否成功 Boolean success = new UserInfo().delete(queryWrapper);
7,查询数据
(1)调用对象的 selectById 方法可以根据主键 id 查询一条记录:UserInfo user = new UserInfo(); user.setId(1); // 根据ID查询数据 user = user.selectById(); /****** 下面代码功能等效上面代码 ********/ UserInfo user= new UserInfo().selectById(1);
(2)调用对象的 selectOne 方法可以使用查询构造器查询一条记录:
注意:如果数据库中符合传入条件的记录有多条,这个方法会返回第一条数据,不会报错。
// 查询条件:名字中包含'ha'并且年龄小于40 QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>(); queryWrapper.like("user_name","ha").lt("age",40); // 开始查询 UserInfo user= new UserInfo().selectOne(queryWrapper);
(3)调用对象的 selectAll 方法可以查询所有的记录:
List<UserInfo> users = new UserInfo().selectAll();
(4)调用对象的 selectList 方法可以使用查询构造器查询数据,返回一个 List:
// 查询条件:名字中包含'ha'并且年龄小于40 QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>(); queryWrapper.like("user_name","ha").lt("age",40); // 开始查询 List<UserInfo> users = new UserInfo().selectList(queryWrapper);
(5)调用对象的 selectCount 方法可以使用查询构造器,查询总记录数:
// 查询条件:名字中包含'ha'并且年龄小于40 QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>(); queryWrapper.like("user_name","ha").lt("age",40); // 开始查询 Integer count = new UserInfo().selectCount(queryWrapper);
(6)调用对象的 selectPage 方法可以实现分页查询,比如下面我们查询第一页的数据(每页两条记录):
这个分页方法和 BaseMapper 提供的分页一样都是物理分页,使用前需要要进行相关的插件配置,具体配置参考我之前的文章:
LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.like(UserInfo::getPassWord,"123").lt(UserInfo::getAge,40); // 开始查询 IPage<UserInfo> page = new UserInfo().selectPage(new Page<>(1,2), queryWrapper);
