Automating Common Entity Fields in Java Backend with MyBatis-Plus, AOP, and JWT
This article presents a production‑tested solution for automatically handling common entity fields such as createTime, updateTime, createUser, and updateUser in Java backend systems, combining MyBatis‑Plus auto‑fill, AOP interceptors, custom annotations, multi‑datasource support, distributed ID generation, and auditing techniques to eliminate repetitive code and reduce bugs.
When developing an order module in a delivery system, each entity class often contains repeated fields like create_time and update_by . Manually maintaining these fields is inefficient and error‑prone.
This article shares a production‑tested automation scheme that includes six core strategies: MyBatis‑Plus automatic filling, AOP, JWT, multi‑datasource adaptation, distributed ID generation, and auditing.
1. Pain points
High code duplication – every Service method must set the fields manually.
High maintenance cost – field changes require modifications in many places.
Easy to miss – especially during update operations.
2. Basic solution: MyBatis‑Plus automatic filling
2.1 Configure MetaObjectHandler
// 订单创建逻辑
public void createOrder(OrderDTO dto) {
Order order = convertToEntity(dto);
// 手动设置公共字段
order.setCreateTime(LocalDateTime.now());
order.setUpdateTime(LocalDateTime.now());
order.setCreateUser(getCurrentUser());
order.setUpdateUser(getCurrentUser());
orderMapper.insert(order);
}
// 订单更新逻辑
public void updateOrder(OrderDTO dto) {
Order order = convertToEntity(dto);
// 重复设置逻辑
order.setUpdateTime(LocalDateTime.now());
order.setUpdateUser(getCurrentUser());
orderMapper.updateById(order);
}2.2 Entity class annotation configuration
@Data
public class BaseEntity {
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private String createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateUser;
}
// 订单实体继承基类
public class Order extends BaseEntity {
// 业务字段...
}3. Advanced solution: AOP unified handling
3.1 Custom annotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AutoFill {
OperationType value();
}
public enum OperationType {
INSERT,
UPDATE
}3.2 Aspect implementation
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
@Autowired
private ObjectMapper objectMapper;
@Around("@annotation(autoFill)")
public Object around(ProceedingJoinPoint pjp, AutoFill autoFill) throws Throwable {
Object[] args = pjp.getArgs();
for (Object arg : args) {
if (arg instanceof BaseEntity) {
fillFields((BaseEntity) arg, autoFill.value());
}
}
return pjp.proceed(args);
}
private void fillFields(BaseEntity entity, OperationType type) {
String currentUser = getCurrentUser();
LocalDateTime now = LocalDateTime.now();
if (type == OperationType.INSERT) {
entity.setCreateTime(now);
entity.setCreateUser(currentUser);
}
entity.setUpdateTime(now);
entity.setUpdateUser(currentUser);
}
private String getCurrentUser() {
return Optional.ofNullable(RequestContextHolder.getRequestAttributes())
.map(attrs -> (ServletRequestAttributes) attrs)
.map(ServletRequestAttributes::getRequest)
.map(req -> req.getHeader("X-User-Id"))
.orElse("system");
}
}4. Production best practices
4.1 Multi‑datasource adaptation
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public MetaObjectHandler metaObjectHandler() {
return new MultiDataSourceAutoFillHandler();
}
}
public class MultiDataSourceAutoFillHandler extends MetaObjectHandler {
// 根据当前数据源动态处理
}4.2 Distributed ID generation
public class SnowflakeIdGenerator {
// 实现分布式ID生成
}
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "id", String.class, idGenerator.nextId());
}5. Pitfall guide
Null‑pointer protection using Optional to safely obtain the current user.
Field overwrite issues solved by setting updateStrategy = FieldStrategy.NEVER on @TableField .
6. Performance optimization
6.1 Cache current user information
public class UserContextHolder {
private static final ThreadLocal
userHolder = new ThreadLocal<>();
public static void setUser(String user) {
userHolder.set(user);
}
public static String getUser() {
return userHolder.get();
}
public static void clear() {
userHolder.remove();
}
}
public class UserInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
UserContextHolder.setUser(request.getHeader("X-User-Id"));
return true;
}
}6.2 Batch operation optimization
@Transactional
public void batchInsert(List<Order> orders) {
// 提前获取公共字段值
String user = getCurrentUser();
LocalDateTime now = LocalDateTime.now();
orders.forEach(order -> {
order.setCreateTime(now);
order.setCreateUser(user);
order.setUpdateTime(now);
order.setUpdateUser(user);
});
orderMapper.batchInsert(orders);
}7. Monitoring and auditing
7.1 Auditing log integration
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
@CreatedBy
private String createUser;
@LastModifiedBy
private String updateUser;
@CreatedDate
private LocalDateTime createTime;
@LastModifiedDate
private LocalDateTime updateTime;
}7.2 Operation log tracing
@Aspect
@Component
public class OperationLogAspect {
@AfterReturning("@annotation(autoFill)")
public void logOperation(AutoFill autoFill) {
LogEntry log = new LogEntry();
log.setOperator(getCurrentUser());
log.setOperationType(autoFill.value().name());
logService.save(log);
}
}By combining these six solutions, the project reduced common‑field code by 90%, lowered related bug rates by 75%, and increased new‑feature development efficiency by 40%.
Best‑practice checklist: use MyBatis‑Plus auto‑fill for basic fields, combine AOP for complex scenarios, integrate unique ID generation in distributed environments, add audit logs for critical operations, and regularly review field‑fill strategies.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.