MyBatis - 自动区分环境

更多MyBatis实战内容,请参考:MyBatis - 实战指南

背景

在开发时,经常会用到测试,甚至是压测。测试数据应该是与正式数据区分开来的。怎么区分呢?我们可以在数据库中的每个表中都添加一个env字段,来表示环境。当env字段为0时,表示为测试数据,为1时表示为正式数据。

在实际使用时,怎么给env设置值呢?

我们可以根据域名来进行区分。比如当域名为api.xxx.com时,表示是正式环境的数据,env设置为1;而当域名是api.test.xxx.com时,表示为测试环境数据,env设置为0

实现方法

在数据库中,env字段是TINYINT,对于的JavaType是EnvEnum

public enum EnvEnum{
    Product(1,"生产环境"),VIRTUAL(0,"虚拟环境");
}

这里,我们假设env字段已经根据域名被设置到ThreadLocal中了。那么在实现拦截器的时候,直接从ThreadLocal中取就是了:

@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class EnvInterceptor implements Interceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(EnvInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        Object object = invocation.getArgs()[1];
        //sql类型
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        if (SqlCommandType.INSERT.equals(sqlCommandType)) {
            //插入操作时,自动插入env。TraceUtil从ThreadLocal众获取env的值
            EnvEnum envEnum = TraceUtil.getEnv();
            Field fieldEnv = object.getClass().getDeclaredField("env");
            fieldEnv.setAccessible(true);
            fieldEnv.set(object, envEnum);
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

最后,注册拦截器到MyBatis plugin:




    
        
    
    
        
    



你可能感兴趣的:(MyBatis - 自动区分环境)