Eliminate Repetitive Common Fields in Java Order Services with MyBatis-Plus, AOP, and JWT

This article presents a production‑tested, six‑step automation strategy—combining MyBatis‑Plus auto‑fill, AOP interceptors, JWT‑based user retrieval, multi‑data‑source handling, distributed ID generation, and audit logging—to completely remove manual maintenance of common fields like create_time and update_by in Java order modules, boosting efficiency and reducing bugs.

Architect
Architect
Architect
Eliminate Repetitive Common Fields in Java Order Services with MyBatis-Plus, AOP, and JWT

Pain Point Analysis: Three Challenges of Common Field Maintenance

When developing the order module of a delivery system, each entity class contains repetitive fields such as create_time and update_by. Manually setting these fields is inefficient and error‑prone.

High code duplication (every Service method repeats the same assignments)

High maintenance cost (field changes require modifications in many places)

Easy to miss (especially during updates)

Basic Solution – MyBatis‑Plus Automatic Fill

2.1 Configure MetaObjectHandler

@Slf4j
@Component
public class AutoFillHandler implements MetaObjectHandler {
    // Insert fill
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, "createUser", String.class, getCurrentUser());
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
        this.strictUpdateFill(metaObject, "updateUser", String.class, getCurrentUser());
    }
    // Update fill
    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
        this.strictUpdateFill(metaObject, "updateUser", String.class, getCurrentUser());
    }
    private String getCurrentUser() {
        return Optional.ofNullable(SecurityContextHolder.getContext())
                .map(SecurityContext::getAuthentication)
                .map(Authentication::getName)
                .orElse("system");
    }
}

2.2 Entity 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 {
    // business fields ...
}

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");
    }
}

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 {
    // Dynamically handle based on current data source
}

4.2 Distributed ID Generation

public class SnowflakeIdGenerator {
    // Implement distributed ID generation
}

@Override
public void insertFill(MetaObject metaObject) {
    this.strictInsertFill(metaObject, "id", String.class, idGenerator.nextId());
}

Pitfall Guide – Five Common Issues

5.1 Null‑Pointer Protection

private String safeGetUser() {
    return Optional.ofNullable(SecurityContextHolder.getContext())
            .map(SecurityContext::getAuthentication)
            .map(Authentication::getPrincipal)
            .map(principal -> {
                if (principal instanceof UserDetails) {
                    return ((UserDetails) principal).getUsername();
                }
                return principal.toString();
            })
            .orElse("system");
}

5.2 Field Overwrite Issue

@TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER)
private String createUser;

Performance Optimization

6.1 Cache Current User Information

public class UserContextHolder {
    private static final ThreadLocal<String> 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);
}

Monitoring and Auditing

7.1 Audit 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);
    }
}

Conclusion

Common‑field maintenance code reduced by 90%.

Related bug rate decreased by 75%.

New feature development efficiency increased by 40%.

Best‑Practice Checklist

Use MyBatis‑Plus auto‑fill for basic fields.

Combine AOP for complex scenarios.

Integrate distributed ID generation in micro‑service environments.

Add audit logs for critical operations.

Regularly review field‑fill strategies.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

aopCode Optimizationmybatis-pluscommon-fieldsautomatic-fill
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.