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> entrySet = ((Map) parameter).entrySet();
   for (Entry 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();
	}


}

 

你可能感兴趣的:(java)