mybatis 自動填充時間字段

本例項目實踐過程中,數據模型創建包含公共字段(創建時間createTime,最後更新時間last_updated_time),爲了開發人員方便,打算自動填充時間公共字段;本例數據庫採用oceanbase; 以下2種方式,可以處理以下場景問題

1. 從數據庫表創建角度解決,表創建時給時間字段加上默認值,例如下面案例

CREATE TABLE TEST (
	ID VARCHAR(100) DEFAULT NULL,
	CREATE_TIME DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
	LAST_UPDATE_TIME DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
	PRIMARY KEY (`ID`)
);

 2. 在mybatis攔截器層解決

本案例 dao層 insert 或者 update 方法參數是實體,如果參數是其他類型參數,比如Map類型,也可以在攔截器實現

解決思路,在生成的實例類中的時間字段標記註解,在mybatis攔截器鏈執行Executor 階段填充時間

1)自定義註解

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface CreateTime {
	
	String value() default "";
	
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface UpdateTime {
	
	String value() default "";
	
}

 2) 添加攔截器

@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class GenerateTimeIntercepter implements Interceptor {

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
		// sql 類型
		SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
		// 獲取參數
		Object parameter = invocation.getArgs()[1];
		// 獲取私有成員變量
		Field[] declaredFields = parameter.getClass().getDeclaredFields();
		for (Field field : declaredFields) {
			if (field.getAnnotation(CreateTime.class) != null) {
				// insert 語句插入 createTime
				if (SqlCommandType.INSERT.equals(sqlCommandType)) {
					field.setAccessible(true);
					field.set(parameter, new Date());
				}
			}
			if (field.getAnnotation(UpdateTime.class) != null) {
				// insert 或 update 語句插入 updateTime
				if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
					field.setAccessible(true);
					field.set(parameter, new Date());
				}
			}
		}
		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		if (target instanceof org.apache.ibatis.executor.Executor) {
			return Plugin.wrap(target, this);
		}
		return target;
	}

	@Override
	public void setProperties(Properties properties) {
	}

參數類型是Map

@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class GenerateTimeIntercepter implements Interceptor {


 @SuppressWarnings({ "unchecked", "rawtypes" })
 @Override
 public Object intercept(Invocation invocation) throws Throwable {
  MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
  // sql 類型
  SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
  // 獲取參數
  Object parameter = invocation.getArgs()[1];
  
  if (parameter instanceof Map) {
   //支持批量batchInsert 插入時間字段
   Set<Entry<String, Object>> entrySet = ((Map<String, Object>) parameter).entrySet();
   for (Entry<String, Object> set : entrySet) {
    Object value = set.getValue();
    if (value instanceof List) {
     List tempList = (List) value;
     for (int i = 0; i < tempList.size(); i++) {
      Object obj = tempList.get(i);
      Field[] declaredFields = obj.getClass().getDeclaredFields();
      fillTime(declaredFields, sqlCommandType, obj);
     }
    }
   }
  }else {
   // update 或者insert 執行此段邏輯
   // 獲取私有成員變量
   Field[] declaredFields = parameter.getClass().getDeclaredFields();
   // 填充時間字段值
   fillTime(declaredFields, sqlCommandType, parameter);
  }
  return invocation.proceed();
 }

 public void fillTime(Field[] declaredFields, SqlCommandType sqlCommandType, Object parameter) throws Throwable {
  for (Field field : declaredFields) {
   if (field.getAnnotation(CreateTime.class) != null) {
    // insert 語句插入 createTime
    if (SqlCommandType.INSERT.equals(sqlCommandType)) {
     field.setAccessible(true);
     field.set(parameter, new Date());
    }
   }
   if (field.getAnnotation(UpdateTime.class) != null) {
    // insert 或 update 語句插入 updateTime
    if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
     field.setAccessible(true);
     field.set(parameter, new Date());
    }
   }
  }

3. 注入攔截器

@Configuration
public class MybatisConfiguration {
	
	/**
	 *  自定義插入CreateTime ,UpdateTime 時間
	 * @return
	 */
	@Bean
	public GenerateTimeIntercepter generateTimeIntercepter() {
		return new GenerateTimeIntercepter();
	}


}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章