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