Mybatis-Plus实战:活用Model继承,解锁实体类CRUD新姿势
1. 为什么需要让实体类继承Model?
在日常开发中,我们使用Mybatis-Plus时最熟悉的模式就是:先定义实体类,然后创建对应的Mapper接口,最后在Service层调用Mapper完成数据库操作。这种模式虽然清晰,但每个简单的CRUD操作都需要经过这几个步骤,显得有些繁琐。
我最近在一个用户管理模块的开发中就深有体会。当时需要快速实现一批基础的用户增删改查接口,按照传统方式,每个操作都要写Mapper方法、Service方法,虽然Mybatis-Plus的BaseMapper已经帮我们封装了常用方法,但还是要写不少样板代码。直到我发现了Model继承这个特性,才真正体会到什么叫"少写代码多做事"。
让实体类继承Model的最大好处就是:实体类可以直接调用CRUD方法,不再必须通过Mapper接口。这就好比给你的实体类装上了翅膀,让它能自己飞向数据库,而不需要每次都通过Mapper这个"中介"。在实际项目中,对于简单的单表操作,这种模式能减少至少30%的代码量。
2. 5分钟快速上手Model继承
2.1 环境准备
首先确保你的Spring Boot项目已经引入了Mybatis-Plus的starter依赖。我建议使用最新稳定版,目前是3.5.3.1:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency>2.2 实体类改造
让我们以一个用户管理系统为例。传统的User实体类是这样的:
@Data public class User { private Long id; private String username; private String password; // 其他字段和getter/setter }要启用Model继承特性,只需要做一个小改动:
@Data @TableName("sys_user") // 指定对应的表名 public class User extends Model<User> { private Long id; private String username; private String password; // 必须重写这个方法,返回主键字段名 @Override protected Serializable pkVal() { return this.id; } }这里有几个关键点需要注意:
- 必须继承
Model<T>,其中泛型T就是当前实体类 - 必须使用
@TableName注解指定对应的数据库表名 - 必须重写
pkVal()方法,返回主键字段的值
2.3 基础CRUD操作
改造后的User实体类立刻获得了强大的自操作能力:
// 新增用户 User user = new User(); user.setUsername("张三"); user.setPassword("123456"); user.insert(); // 直接插入数据库 // 查询用户 User dbUser = user.selectById(1L); // 更新用户 dbUser.setPassword("654321"); dbUser.updateById(); // 删除用户 dbUser.deleteById();是不是非常简单?这些方法都是Model基类提供的,开箱即用。我在实际项目中使用后发现,对于简单的单表操作,这种模式比传统的Mapper方式要简洁得多。
3. 深入理解Model的实现原理
3.1 Model类的方法解析
Model类之所以能让实体类具备CRUD能力,是因为它内部封装了一个SqlHelper对象,所有数据库操作最终都会通过它来执行。我们来看几个核心方法的实现:
public boolean insert() { return SqlHelper.retBool(sqlSession().insert(sqlStatement(SqlMethod.INSERT_ONE), this)); } public boolean updateById() { return SqlHelper.retBool(sqlSession().update(sqlStatement(SqlMethod.UPDATE_BY_ID), this)); }可以看到,这些方法底层还是调用了Mybatis的SqlSession,只是帮我们封装了这些重复操作。
3.2 必须创建Mapper接口的原因
虽然实体类可以直接操作数据库,但我们仍然需要创建对应的Mapper接口:
@Mapper public interface UserMapper extends BaseMapper<User> { }这是因为Mybatis-Plus在启动时需要扫描这些Mapper来构建元数据。如果没有Mapper,会抛出Not Found TableInfoCache异常。不过好消息是,这个Mapper接口可以完全为空,不需要定义任何方法。
4. 高级查询技巧
4.1 条件查询
除了基本的CRUD,Model还支持各种条件查询。比如要查询所有年龄大于18的用户:
List<User> users = new User().selectList( new QueryWrapper<User>().gt("age", 18) );4.2 链式调用
Model还支持链式调用,让代码更加流畅:
boolean success = new User() .setUsername("李四") .setPassword("123456") .insert();4.3 批量操作
虽然Model主要针对单条记录操作,但也可以实现批量功能:
// 批量插入 List<User> userList = ...; new User().insertBatch(userList); // 根据ID批量查询 List<User> users = new User().selectBatchIds(Arrays.asList(1L, 2L, 3L));5. 实际项目中的经验分享
在使用Model继承的过程中,我踩过几个坑,这里分享给大家:
分页查询:Model本身不支持分页查询,复杂的分页还是需要通过Mapper来实现。我通常的做法是简单查询用Model,复杂查询用Mapper。
事务管理:多个Model操作默认不会在同一个事务中,如果需要事务,还是要使用
@Transactional注解。性能考虑:对于高频操作,Model方式会比Mapper方式稍慢,因为每次操作都要解析SQL。在对性能要求极高的场景下,建议还是使用Mapper。
适合场景:Model继承最适合简单的单表CRUD操作。如果涉及多表关联、复杂查询等,传统的Mapper方式会更合适。
在我的用户管理模块中,最终采用了混合模式:基础的用户增删改查使用Model继承,而用户角色关联查询等复杂操作仍然使用Mapper。这种组合方式既保持了代码简洁,又不失灵活性。
