1. 需求:对数据库id统一生成
2. 实现方案:通过mybatis拦截器,拦截sql,对要插入的数据重置id
3. 上代码:
/** * @author yangxj * @date 2020-08-10 15:57 * <p> * 自定义id生成器 */ @Component @Intercepts(@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})) public class IDGeneratorPlugin implements Interceptor { // 实体主键字段 private final static String ID_FIELD = "id"; @Override @SuppressWarnings("unchecked") public Object intercept(Invocation invocation) throws Throwable { MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; Object param = invocation.getArgs()[1]; SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType(); // 非插入类型跳过 if (!sqlCommandType.equals(SqlCommandType.INSERT)) { return invocation.proceed(); } // 参数类型 map or entity // 注: mybatis在处理多参数,以及参数类型为集合时,会将参数转map类型处理 if (param instanceof Map) { Map paramMap = (Map)param; // 是否为批量插入操作 Optional batchParam = paramMap.values().stream().filter(paramValues -> paramValues instanceof List).findFirst(); if (batchParam.isPresent()) { for (Object o : (List) batchParam.get()) { restId(o); // 设置id } } else { paramMap.put(ID_FIELD, IdUtil.fastSimpleUUID()); // 设置id } } else { restId(param); } return invocation.proceed(); } private void restId(Object param) { try { Field id = param.getClass().getDeclaredField(ID_FIELD); id.setAccessible(true); //TODO id生成逻辑自实现 if (Objects.isNull(id.get(param))) { id.set(param, IdUtil.fastSimpleUUID()); } } catch (Exception e) { } } @Override public Object plugin(Object target) { return target instanceof Executor ? (Plugin.wrap(target, this)) : target; } @Override public void setProperties(Properties properties) { } }
4. over