参考资料:
- 使用MyBatis拦截器后,定义摸鱼时间又长了。参数🐟
目录
- 一. 🤔需求场景
- 二. 🤠前期准备
- 三. 💪自定义拦截器
- 四. 👉添加拦截器到配置类中
- 五. 😋效果
一. 🤔需求场景
如下图所示
- 有一个订单信息表,拦截每当插入或者更新一条数据的时候,红框所示部分的字段都需要进行赋值处理.
- 如果还有其他表中也存在红框中的所示字段,每次插入或者更新时也都需要进行赋值操作,很是繁琐。
🐳有没有一种办法,定义能再插入或者更新数据库指定字段的时候,自动替我们处理呢?这就用到了Mybatis中的拦截器.
二. 🤠前期准备
⏹定义一个接口,用来标记实现了此接口的参数类中的参数会被自动处理
public interface AutoHandleParam { }
⏹定义order_info
表的映射实体类
import lombok.Data;import java.util.Date;@Datapublic class OrderInfoEntity implements AutoHandleParam { private String orderId; private String orderName; private String createUserId; private Date createTime; private String updateUserId; private Date updateTime;}
⏹查询接口
public interface OrderInfoMapper { void insertOrderInfo(OrderInfoEntity entity); void updateOrderInfo(OrderInfoEntity entity);}
⏹反射封装类ReflectionUtil
,详情见这篇文章 Java 封装反射工具类
三. 💪自定义拦截器
import com.example.jmw.common.utils.ReflectionUtil;import com.example.jmw.entity.AutoHandleParam;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.springframework.stereotype.Component;import org.springframework.util.ObjectUtils;import java.util.Arrays;import java.util.Date;import java.util.List;import java.util.Properties;@Component@Intercepts({ @Signature( type = Executor.class, method = "update", args = { MappedStatement.class, Object.class} )})public class MybatisParamInterceptor implements Interceptor { // 需要拦截的Mybatis中的操作 private final static String INSERT = "INSERT"; private final static String UPDATE = "UPDATE"; private final static ListsqlCommandTypeList = Arrays.asList(INSERT, UPDATE); @Override public Object intercept(Invocation invocation) throws Throwable { MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; // 获取Mybatis的当前操作方法名称 String sqlCommandType = mappedStatement.getSqlCommandType().name(); if (!sqlCommandTypeList.contains(sqlCommandType)) { return invocation.proceed(); } if (invocation.getArgs().length < 2) { return invocation.proceed(); } // 获取Mybatis插入或更新时传入的参数对象 Object paramEntity = invocation.getArgs()[1]; this.interceptInsertOrUpdateMethod(sqlCommandType, paramEntity); return invocation.proceed(); } /** * 插入或更新时的参数拦截方法 * @param methodName Mybatis方法名称 * @param paramEntity 参数实体类 */ private void interceptInsertOrUpdateMethod(String methodName, Object paramEntity) { // 如果该对象没有实现AutoHandleParam接口的话,就不需要自动添加参数 if (!(paramEntity instanceof AutoHandleParam)) { return; } // 系统默认的用户名 String userId = "系统用户名" + System.currentTimeMillis(); // 当前的系统时间 Date systemDate = new Date(); // 若Mybatis的当前方法为INSERT if (INSERT.equals(methodName)) { // 若实体类中存在此字段 if (ReflectionUtil.existsField(paramEntity, "createUserId")) { Object createUserId = ReflectionUtil.invokeGetterMethod(paramEntity, "createUserId"); if (ObjectUtils.isEmpty(createUserId) || "".equals(createUserId.toString())) { // 通过反射将用户ID放入实体类中 ReflectionUtil.invokeSetterMethod(paramEntity, "createUserId", userId); } } if (ReflectionUtil.existsField(paramEntity, "createTime")) { Object createTime = ReflectionUtil.invokeGetterMethod(paramEntity, "createTime"); if (ObjectUtils.isEmpty(createTime) ) { ReflectionUtil.invokeSetterMethod(paramEntity, "createTime", systemDate); } } return; } // 若Mybatis的当前方法为UPDATE if (UPDATE.equals(methodName)) { if (ReflectionUtil.existsField(paramEntity, "updateUserId")) { ReflectionUtil.invokeSetterMethod(paramEntity, "updateUserId", userId); } if (ReflectionUtil.existsField(paramEntity, "updateTime")) { ReflectionUtil.invokeSetterMethod(paramEntity, "updateTime", systemDate); } } } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { }}
四. 👉添加拦截器到配置类中
import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;import javax.sql.DataSource;@Configurationpublic class DataSourceConfig { // 注入数据源 @Resource private DataSource dataSource; // 注入自定义参数拦截器 @Resource private MybatisParamInterceptor paramInterceptor; @Bean public SqlSessionFactory sqlSessionFactorySecondary() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); // 设置数据源 sqlSessionFactoryBean.setDataSource(dataSource); // 设置拦截器(可设置多个) Interceptor[] plugins = { paramInterceptor}; sqlSessionFactoryBean.setPlugins(plugins); return sqlSessionFactoryBean.getObject(); }}
五. 😋效果
⭕操作之前,表中没有数据
⏹插入一条数据
- 可以看到我们并没有向参数实体类中传入用户ID和创建时间,拦截但是拦截器替我们向实体类中放入了参数,因此最终用户ID和创建时间插入到数据库中了。
⏹更新一条数据
- 可以看到指定的定义订单名称被更新,并且更新用户ID和更新时间也被自动处理到数据库中