偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

SpringBoot 公共字段自動(dòng)填充實(shí)戰(zhàn)

開(kāi)發(fā) 前端
在開(kāi)發(fā)外賣系統(tǒng)訂單模塊時(shí),我發(fā)現(xiàn)每個(gè)實(shí)體類都包含create_time、update_by等重復(fù)字段。手動(dòng)維護(hù)這些字段不僅效率低下,還容易出錯(cuò)。本文將分享一套經(jīng)過(guò)生產(chǎn)驗(yàn)證的自動(dòng)化方案,助你徹底擺脫公共字段維護(hù)的煩惱。

在開(kāi)發(fā)外賣系統(tǒng)訂單模塊時(shí),我發(fā)現(xiàn)每個(gè)實(shí)體類都包含create_time、update_by等重復(fù)字段。手動(dòng)維護(hù)這些字段不僅效率低下,還容易出錯(cuò)。

本文將分享一套經(jīng)過(guò)生產(chǎn)驗(yàn)證的自動(dòng)化方案,助你徹底擺脫公共字段維護(hù)的煩惱。

一、痛點(diǎn)分析:公共字段維護(hù)的三大困境

1.1 典型問(wèn)題場(chǎng)景
// 訂單創(chuàng)建邏輯
public void createOrder(OrderDTO dto) {
    Order order = convertToEntity(dto);
    
    // 手動(dòng)設(shè)置公共字段
    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);
    
    // 重復(fù)設(shè)置邏輯
    order.setUpdateTime(LocalDateTime.now());
    order.setUpdateUser(getCurrentUser());
    
    orderMapper.updateById(order);
}

痛點(diǎn)總結(jié):

  • 代碼重復(fù)率高(每個(gè)Service方法都要設(shè)置)
  • 維護(hù)成本高(字段變更需修改多處)
  • 容易遺漏(特別是更新操作)

二、基礎(chǔ)方案:MyBatis-Plus自動(dòng)填充

2.1 配置元對(duì)象處理器
@Slf4j
@Component
publicclass AutoFillHandler implements MetaObjectHandler {
    
    // 插入時(shí)自動(dòng)填充
    @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());
    }

    // 更新時(shí)自動(dòng)填充
    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
        this.strictUpdateFill(metaObject, "updateUser", String.class, getCurrentUser());
    }
    
    // 獲取當(dāng)前用戶(從安全上下文)
    private String getCurrentUser() {
        return Optional.ofNullable(SecurityContextHolder.getContext())
                      .map(SecurityContext::getAuthentication)
                      .map(Authentication::getName)
                      .orElse("system");
    }
}
2.2 實(shí)體類注解配置
@Data
publicclass 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;
}

// 訂單實(shí)體繼承基類
publicclass Order extends BaseEntity {
    // 業(yè)務(wù)字段...
}

三、進(jìn)階方案:AOP統(tǒng)一處理

3.1 自定義注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AutoFill {
    OperationType value();
}

public enum OperationType {
    INSERT,
    UPDATE
}
3.2 切面實(shí)現(xiàn)
@Aspect
@Component
@Slf4j
publicclass 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);
    }
    
    // 獲取當(dāng)前用戶(支持多線程環(huán)境)
    private String getCurrentUser() {
        return Optional.ofNullable(RequestContextHolder.getRequestAttributes())
                      .map(attrs -> (ServletRequestAttributes) attrs)
                      .map(ServletRequestAttributes::getRequest)
                      .map(req -> req.getHeader("X-User-Id"))
                      .orElse("system");
    }
}

四、生產(chǎn)環(huán)境最佳實(shí)踐

4.1 多數(shù)據(jù)源適配
@Configuration
publicclass DataSourceConfig {
    
    @Bean
    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        returnnew MultiDataSourceAutoFillHandler();
    }
}

publicclass MultiDataSourceAutoFillHandler extends MetaObjectHandler {
    // 根據(jù)當(dāng)前數(shù)據(jù)源動(dòng)態(tài)處理
}
4.2 分布式ID生成
public class SnowflakeIdGenerator {
    // 實(shí)現(xiàn)分布式ID生成
}

// 在自動(dòng)填充中集成
@Override
public void insertFill(MetaObject metaObject) {
    this.strictInsertFill(metaObject, "id", String.class, 
        idGenerator.nextId());
}

五、避坑指南:五大常見(jiàn)問(wèn)題

5.1 空指針異常防護(hù)
// 使用Optional處理可能為空的情況
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 字段覆蓋問(wèn)題
// 在實(shí)體類中使用@TableField策略
@TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER)
private String createUser;

六、性能優(yōu)化方案

6.1 緩存當(dāng)前用戶信息
public class UserContextHolder {
    privatestaticfinal 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();
    }
}

// 在攔截器中設(shè)置
publicclass UserInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler) {
        UserContextHolder.setUser(request.getHeader("X-User-Id"));
        returntrue;
    }
}
6.2 批量操作優(yōu)化
@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);
}

七、監(jiān)控與審計(jì)

7.1 審計(jì)日志集成
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
    @CreatedBy
    private String createUser;
    
    @LastModifiedBy
    private String updateUser;
    
    @CreatedDate
    private LocalDateTime createTime;
    
    @LastModifiedDate
    private LocalDateTime updateTime;
}
7.2 操作日志追蹤
@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);
    }
}

結(jié)語(yǔ): 通過(guò)本文的六種方案組合使用,我們?cè)谏a(chǎn)環(huán)境中實(shí)現(xiàn)了:

  • 公共字段維護(hù)代碼量減少90%
  • 相關(guān)Bug率下降75%
  • 新功能開(kāi)發(fā)效率提升40%

最佳實(shí)踐清單:

  • 基礎(chǔ)字段使用MyBatis-Plus自動(dòng)填充
  • 復(fù)雜場(chǎng)景結(jié)合AOP處理
  • 分布式環(huán)境集成唯一ID生成
  • 重要操作添加審計(jì)日志
  • 定期檢查字段填充策略
責(zé)任編輯:武曉燕 來(lái)源: 一安未來(lái)
相關(guān)推薦

2020-09-21 08:32:03

JavaSQL公共字段

2025-05-27 01:44:00

2025-05-29 03:00:00

2021-01-05 05:36:39

設(shè)計(jì)Spring Boot填充

2023-02-15 09:34:20

公共字段mybatis變量

2021-02-07 19:20:27

微軟自動(dòng)填充瀏覽器

2021-01-20 07:10:29

微軟 瀏覽器Edge

2024-05-15 11:09:30

2025-03-26 08:43:17

2013-01-05 09:29:44

戴爾Credant并購(gòu)

2024-06-20 08:26:01

JPA公共字段

2011-08-18 10:22:44

2009-07-15 17:01:29

iBATIS操作CLO

2017-01-17 14:26:15

2021-11-10 10:03:18

SpringBootJava代碼

2022-08-08 07:33:11

自動(dòng)裝配Java容器

2022-09-06 08:54:00

SpringBootController

2020-06-29 07:43:12

緩存RedisSpringBoot

2021-04-08 13:46:30

Edge微軟瀏覽器

2018-07-04 11:01:48

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)