MyBatis-Plus
MyBatis-Plus
MyBatis-Plus(MP)是MyBatis的增强工具,它简化了基础的增删改查、实体映射、逻辑删除等操作,通过提供一系列自动帮手类和插件,极大地减轻了开发者的编码负担。
1. MyBatis-Plus原理概述
MyBatis-Plus的核心在于其生成的BaseMapper
接口和IService
接口。这些接口内部集成了众多通用方法,基于这些方法,MP能够简化常见的数据库操作。
- BaseMapper:这是自动生成的映射器接口,它继承了
Mapper<T>
,提供了包括selectList
,insert
,deleteById
,updateById
等常用CRUD方法。 - IService:它扩展了
BaseMapper<T>
的API,提供更高级别的服务方法,如分页查询、基于条件的查询等。
MP实现这些高级功能的背后涉及到反射、动态代理、元注解、SQL解析等多个技术点,简化了开发者对SQL语句的手动编写过程。
2. 动手实践
2.1 环境搭建
首先,需要在Spring Boot项目中添加MyBatis-Plus的依赖:
<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- MyBatis Plus 核心API -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-core</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
配置数据库连接:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: username
password: password
2.2 实体类与Mapper接口
有一个User
实体类:
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@TableName("t_user")
@Data
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}
然后,定义UserMapper接口:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<User> {
}
2.3 服务层实现
创建UserService
实现IService<User>
接口,用于处理业务逻辑:
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
// Implementation
}
2.4 控制器层
在控制器层调用UserService
方法:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
public List<User> getUsers() {
return userService.list();
}
}
3. 高级功能与优化
MyBatis-Plus还提供了许多高级功能,如多条件查询、逻辑删除、字段级填充等。通过Wrapper
类可以构建复杂的查询条件;使用@TableLogic
注解,可以实现逻辑删除;@TableField(fill = FieldFill.INSERT)
注解用于字段自动填充。
3.1 复杂查询条件构造:Wrapper类
在MyBatis-Plus中,Wrapper
类提供了一种灵活的方式,可以构建复杂的SQL查询条件。下面是一个使用QueryWrapper
组合查询条件的示例:
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
List<User> users = userService.list(new QueryWrapper<User>()
.eq("age", 25)
.gt("score", 80)
.orderByDesc("score"));
在这个例子中,根据age
和score
字段来筛选用户,并按score
降序排列。
3.2 逻辑删除
逻辑删除是MyBatis-Plus的一个强大特性,它可以避免直接从数据库中永久移除数据。要在实体类中启用逻辑删除,需要进行以下配置:
@Entity
@Table(name = "t_user", schema = "...")
@IdClass(User.class)
@TableName("t_user")
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
@TableLogic
private Boolean deleted;
// getters and setters...
}
然后在Mapper或Service中使用删除方法时,需要指定逻辑删除的处理:
// 在serviceImpl中覆盖删除方法以使用逻辑删除
public boolean removeById(Serializable id) {
return removeByIds(Collections.singletonList(id), true);
}
public boolean removeByIds(Collection<? extends Serializable> idList) {
return removeByIds(idList, true);
}
private boolean removeByIds(Collection<? extends Serializable> idList, boolean deleted) {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.in("id", idList).set("deleted", deleted);
return userMapper.update(null, updateWrapper) > 0;
}
3.3 字段填充
字段自动填充是MyBatis-Plus的又一个实用功能。可以使用@TableField
注解中的fill = FieldFill.INSERT
或fill = FieldFill.INSERT_UPDATE
来指定在插入时或更新时填充字段。
有这样三个需要自动填充的字段:
// 创建时间,在插入时填充
@TableField(fill = FieldFill.INSERT)
private Date createTime;
// 更新时间,在插入和更新时都填充
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
// 是否删除,默认值是false
@TableField(fill = FieldFill.INSERT, defaultValue = "false")
private Boolean deletedFlag;
3.4 分页和排序
MyBatis-Plus提供了一个方便的分页查询方法。接下来是一个获取第一页前三条记录的示例:
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
Page<User> page = new Page<>(1, 3); // page是第1页,每页大小是3
IPage<User> userPage = userService.page(page, new QueryWrapper<User>().orderByDesc("age"));
然后,可以通过userPage
对象访问总页数、总记录数等信息。
3.5. 全局拦截器
全局拦截器可用于处理常见的业务需求,如添加公共的查询条件或修改查询结果。假设想在所有查询操作中都添加逻辑删除的过滤条件:
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
@Interceptor
public class LogicDeleteInterceptor implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "deleted", Boolean.class, false);
}
@Override
public void updateFill(MetaObject metaObject) {
// 无需加入该逻辑删除的字段
}
}
然后,将该拦截器添加到MyBatisPlus的全局配置中:
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.addInterceptor(new LogicDeleteInterceptor());
}