Mybatis/MybatisPllus公共字段填充与配置逻辑删除
在开发过程中,很多时候需要处理一些公共字段,例如:创建时间、修改时间、状态字段等。这些字段通常会在插入或更新数据时进行填充,以便记录数据的变化和状态。同时,逻辑删除也是常见的业务需求,比如删除记录并不是从数据库中物理删除,而是通过更新某个字段(如 is_deleted
)来标记数据已被删除。
MyBatis 和 MyBatis-Plus 都提供了相应的机制来处理这些公共字段的填充和逻辑删除。下面我们将分别介绍如何在 MyBatis 和 MyBatis-Plus 中实现公共字段填充与逻辑删除。
1.公共字段填充
mybatis:
在 MyBatis 中,公共字段填充可以通过 TypeHandler
或者使用拦截器(Interceptor)来实现。但更为常见且方便的方式是通过 插件
(例如 MyBatis Plus
)来进行全局配置。下面我们讲解一种使用拦截器的方式来实现公共字段填充。
MyBatis 支持通过拦截器(Interceptor)来修改执行的 SQL,或者在执行时进行公共字段的填充。你可以定义一个 Interceptor
,在插入或更新操作前对公共字段进行填充:
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Component
public class MybatisInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 获取当前执行的 SQL
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
BoundSql boundSql = statementHandler.getBoundSql();
// 获取 SQL 类型(插入或更新)
String sql = boundSql.getSql();
if (sql.trim().toUpperCase().startsWith("INSERT")) {
// 如果是插入操作,填充公共字段
sql = addCommonFieldsForInsert(sql);
} else if (sql.trim().toUpperCase().startsWith("UPDATE")) {
// 如果是更新操作,填充公共字段
sql = addCommonFieldsForUpdate(sql);
}
// 更新 SQL
boundSql.setSql(sql);
return invocation.proceed();
}
private String addCommonFieldsForInsert(String sql) {
// 获取当前用户信息(例如从 ThreadLocal 中获取当前用户)
String currentUser = getCurrentUser();
// 添加创建时间、更新时间、创建人、更新人等字段
sql = sql.replace("(", "(create_time, update_time, create_by, update_by, ");
sql = sql.replace("values", "values(now(), now(), '" + currentUser + "', '" + currentUser + "', ");
return sql;
}
private String addCommonFieldsForUpdate(String sql) {
// 获取当前用户信息(例如从 ThreadLocal 中获取当前用户)
String currentUser = getCurrentUser();
// 替换 SQL,设置更新时间、更新人
if (sql.contains("set")) {
sql = sql.replaceFirst("set", "set update_time = now(), update_by = '" + currentUser + "', ");
}
return sql;
}
private String getCurrentUser() {
// 模拟获取当前用户,实际情况可以通过 ThreadLocal 或 SecurityContext 获取
return "admin"; // 假设当前用户是 admin
}
记得要把拦截器注册
mybatis-plus:
通过实现MetaObjectHandler
接口简化处理。
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 获取当前登录用户,假设是通过 ThreadLocal 获取当前用户
String currentUser = getCurrentUser();
this.strictInsertFill(metaObject, "createBy", String.class, currentUser);
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
this.strictInsertFill(metaObject, "updateBy", String.class, currentUser);
this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
// 获取当前登录用户,假设是通过 ThreadLocal 获取当前用户
String currentUser = getCurrentUser();
this.strictUpdateFill(metaObject, "updateBy", String.class, currentUser);
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
private String getCurrentUser() {
// 假设当前用户信息存储在 ThreadLocal 中
return "admin"; // 或者从上下文中获取
}
}
2.逻辑删除:
1. MyBatis实现方式
需手动修改所有SQL语句或在拦截器中添加条件。
XML映射文件示例
<select id="selectById" resultType="User">
SELECT * FROM user WHERE id = #{id} AND is_deleted = 0
</select>
<update id="deleteById">
UPDATE user SET is_deleted = 1 WHERE id = #{id}
</update>
运行 HTML
2. MyBatis-Plus实现方式
提供全局配置和注解两种方式。
方式1:全局配置(application.yml)
mybatis-plus:
global-config:
db-config:
logic-delete-field: isDeleted # 逻辑删除字段名
logic-delete-value: 1 # 删除标记值
logic-not-delete-value: 0 # 未删除标记值
方式2:注解标记
public class User {
@TableLogic
private Integer isDeleted;
}
方式3:Java配置类
@Configuration
public class MyBatisPlusConfig {
@Bean
public GlobalConfig globalConfig() {
GlobalConfig config = new GlobalConfig();
GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
dbConfig.setLogicDeleteField("isDeleted");
dbConfig.setLogicDeleteValue("1");
dbConfig.setLogicNotDeleteValue("0");
config.setDbConfig(dbConfig);
return config;
}
}