在日常開發(fā)業(yè)務(wù)場景中,經(jīng)常要遇到對 實體進行通用性操作蛾茉,如:
- 進行持久化時谦炬,出現(xiàn)的保存 創(chuàng)建人信息
- 更新數(shù)據(jù)時候节沦,通用更新 操作人信息
- 指定接口自定義主鍵甫贯,等
為了解決這類問題赔桌,可以采用AOP 也可以采用攔截器疾党,以下是采用MyBatis攔截器進行實現(xiàn)的
設(shè)置通用實體參數(shù)
@Data
public class BaseEntity {
@TableId
private String id;
private Date createTime;
/**
* 刪除狀態(tài):
* 1 : 已刪除
* 0 :未刪除
*/
@Column(nullable = false)
private Integer isDeleted;
}
@Data
@MappedSuperclass
public class CommonBaseEntity extends BaseEntity implements CreatorSetterImpl, UpdaterSetterImpl {
/**
* 創(chuàng)建人ID
*/
private String creatorId;
/**
* 創(chuàng)建人姓名
*/
private String creatorName;
/**
* 最后更新人ID
*/
private String updaterId;
/**
* 最后更新人姓名
*/
private String updaterName;
/**
* 最后更新時間
*/
private Date updateTime;
}
創(chuàng)建用戶接口 CreatorSetterImpl
public interface CreatorSetterImpl {
void setCreatorId(String creatorId);
void setCreatorName(String creatorName);
}
更新用戶接口 UpdaterSetterImpl
public interface UpdaterSetterImpl {
void setUpdaterId(String updaterId);
void setUpdaterName(String updaterName);
void setUpdateTime(Date updateTime);
}
編寫攔截器
/**
* @ClassName: BaseEntityMapperInterceptor
* @Author: ren
* @Description:
* @CreateTIme: 2019/7/8 0008 下午 5:26
**/
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class BaseEntityMapperInterceptor implements Interceptor, WapperInterface {
@Override
public Object intercept(Invocation invocation) throws Throwable {
//獲取代理對象梨撞,由于注解的反射卧波,返回的為 確定類型 StatementHandler 的實例對象
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
//通過包裝類幽勒,把statementHandler包裝成一個可以調(diào)用反射的代理對象
MetaObject metaObject = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY);
//事實上攔截到的時RoutingStatementHandler锈颗,需要調(diào)用其中的 delegate 屬性咪惠,才可以調(diào)用到 mappedStatement覆醇,然后通過反射調(diào)用獲取到mappedStatement對象
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
DefaultParameterHandler parameterHandler = (DefaultParameterHandler) metaObject.getValue("delegate.parameterHandler");
//獲取查詢映射的名稱
String id = mappedStatement.getId();
String methodName = id.substring(id.lastIndexOf(".") + 1);
Log4jUtils.getInstance(getClass()).debug("進行通用攔截:" + methodName);
Object parameter = parameterHandler.getParameterObject();
if (methodName.matches("save.*")) {
// 配置通用變量
initSaveMethod(parameter);
if (parameter instanceof HashMap) {
HashMap map = (HashMap) parameter;
map.forEach((k, v) -> {
if (v instanceof Collection) {
Collection collection = (Collection) v;
collection.forEach(obj -> {
// 配置通用變量
initSaveMethod(obj);
});
}
});
}
} else if (methodName.matches("update.*")) {
initUpdateMethod(parameter);
if (parameter instanceof HashMap) {
HashMap map = (HashMap) parameter;
map.forEach((k, v) -> {
if (v instanceof Collection) {
Collection collection = (Collection) v;
collection.forEach(obj -> {
// 配置通用變量
initUpdateMethod(obj);
});
}
});
}
}
return invocation.proceed();
}
/**
* 配置通用更新方法
*
* @param parameter
*/
private void initUpdateMethod(Object parameter) {
if (parameter instanceof UpdaterSetterImpl) {
UserEntity user = UserContext.getUserEntity();
if (null != user) {
UpdaterSetterImpl setter = (UpdaterSetterImpl) parameter;
setter.setUpdaterId(user.getUserId());
setter.setUpdaterName(user.getUsername());
setter.setUpdateTime(new Date());
}
}
}
/**
* 配置通用新增方法
*
* @param parameter
*/
private void initSaveMethod(Object parameter) {
if (parameter instanceof BaseEntity) {
Log4jUtils.getInstance(getClass()).debug("配置通用持久化變量");
BaseEntity baseEntity = (BaseEntity) parameter;
baseEntity.setId(IdWorker.getIdStr());
baseEntity.setIsDeleted(0);
baseEntity.setCreateTime(new Date());
}
if (parameter instanceof CreatorSetterImpl) {
Log4jUtils.getInstance(getClass()).debug("配置創(chuàng)建人信息");
UserEntity user = UserContext.getUserEntity();
if (null != user) {
CreatorSetterImpl setter = (CreatorSetterImpl) parameter;
setter.setCreatorId(user.getUserId());
setter.setCreatorName(user.getUsername());
}
}
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
在Myabtis配置中加入攔截器
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置全局變量 -->
<settings>
<!-- jdbc用getGeneratedKeys 獲取數(shù)據(jù)庫自增鍵值 -->
<setting name="useGeneratedKeys" value="true" />
<!-- 使用列別名替代列名 select name as title from table -->
<setting name="useColumnLabel" value="true" />
<!-- 開啟駝峰命名法: Table(create_time) ->createTime -->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
<plugins>
<plugin interceptor="com.example.oldguy.modules.commons.interceptors.BaseEntityMapperInterceptor"/>
<!--<plugin interceptor="com.example.oldguy.modules.commons.interceptors.BaseEntityInterceptor"/>-->
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"/>
</plugins>
</configuration>