MyBatis-Plus ⚠️
MyBatis-Plus 是 Spring Boot 生态中最接近 Eloquent 的 ORM。但注意:Java 主流 ORM 设计模式是 Data Mapper,不是 Active Record。
Eloquent vs MyBatis-Plus 核心差异
| 特性 | Eloquent | MyBatis-Plus |
|---|---|---|
| 模式 | Active Record | Data Mapper |
| 模型类 | 继承 Model,自带 CRUD | 纯数据类(Entity)+ 独立的 Mapper 接口 |
| 查询 | User::where('age', '>', 18)->get() | userMapper.selectList(wrapper) |
| 关联 | $user->posts()(模型上定义) | @TableField(exist = false) + 手动查询 |
| 保存 | $user = new User(); $user->save(); | userMapper.insert(user) |
| 更新 | $user->update(['name' => 'foo']) | userMapper.updateById(user) |
| 删除 | $user->delete() | userMapper.deleteById(id) |
三步使用
1. 添加依赖
xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>2. 定义 Entity(数据类)
java
@TableName("users") // 类比 protected $table = 'users'
public class User {
@TableId(type = IdType.AUTO) // 类比 $incrementing = true
private Long id;
private String name;
private String email;
private Integer age;
@TableField("created_at") // 字段名映射(类名下划线→驼峰可省略)
private LocalDateTime createdAt;
@TableField("updated_at")
private LocalDateTime updatedAt;
// getter / setter(必须写,或用 @Data)
}3. 定义 Mapper(类比 Repository)
java
@Mapper // 标记为 MyBatis Mapper
public interface UserMapper extends BaseMapper<User> {
// BaseMapper 已经提供了 CRUD 方法,不需要写 SQL
// 类比 Laravel 中继承 Model 后就有的 create/find/update/delete
}
// 使用
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User findById(Long id) {
return userMapper.selectById(id); // 类比 User::find($id)
}
}CRUD 操作对照
java
// 查询单个
User user = userMapper.selectById(1L); // User::find(1)
User user = userMapper.selectOne(wrapper); // User::where()->first()
// 查询列表
List<User> users = userMapper.selectList(null); // User::all()
List<User> users = userMapper.selectList(wrapper); // User::where()->get()
// 分页
Page<User> page = userMapper.selectPage(new Page<>(1, 10), wrapper); // User::paginate(10)
// 插入
userMapper.insert(user); // User::create($data) 或 $user->save()
// 更新
userMapper.updateById(user); // $user->update()
userMapper.update(user, wrapper); // User::where()->update()
// 删除
userMapper.deleteById(1L); // User::destroy(1)
userMapper.delete(wrapper); // User::where()->delete()
// 计数
Long count = userMapper.selectCount(wrapper); // User::where()->count()条件构建器(Wrapper)
java
// ⚠️ Java 的条件构建器相当于 Eloquent 的 where 链式调用,但用对象封装
// 1. 简单查询
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("email", "foo@bar.com"); // where email = 'foo@bar.com'
User user = userMapper.selectOne(wrapper);
// 2. 多条件
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", "张") // where name like '%张%'
.gt("age", 18) // and age > 18
.orderByDesc("created_at") // order by created_at desc
.last("limit 10"); // 直接追加 SQL
List<User> users = userMapper.selectList(wrapper);
// 3. Lambda 写法(推荐,避免硬编码字段名)
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getEmail, "foo@bar.com") // 用方法引用代替字符串
.ge(User::getAge, 18);⚠️ 常见坑
1. Entity 必须有无参构造器
java
// MyBatis 通过反射创建 Entity 实例,需要无参构造器
// 如果你定义了有参构造器,必须同时加上无参构造器
public User() {} // 必须存在2. 字段名映射规则
MyBatis-Plus 默认开启下划线转驼峰:
created_at→createdAt。 如果数据库字段和 Java 属性不是这种对应关系,需要加@TableField。
3. 分页需要额外配置
java
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}不配的话,
selectPage不会返回总记录数。
4. 插入后获取自增 ID
java
userMapper.insert(user);
Long id = user.getId(); // MyBatis-Plus 会自动把自增 ID 写回 Entity
// 不需要像 PHP 那样 $user->id5. ⭐ 和 Eloquent 最根本的区别
- Eloquent:一个 Model 类既有数据又有操作方法。
$user->name读属性,$user->save()写数据库,都在一个类上。- MyBatis-Plus:Entity 只有数据(字段 + getter/setter),CRUD 操作在 Mapper 上。数据和操作分离。
这个区别来自于设计模式:Eloquent 是 Active Record(一个对象 = 一行数据 + 操作),MyBatis-Plus 是 Data Mapper(数据对象和持久化逻辑分离)。没有谁更好,只是不同的设计哲学。