You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate 6.x中PreLoadEvent.getState()始终返回null问题解决

解决Hibernate 6.x中PreLoadEvent.getState()返回null的问题

问题原因

Hibernate 6.x对实体加载流程做了重构,PreLoadEvent.getState()不再像5.x版本那样返回从数据库读取的原始状态数组,该字段默认会是null。

方案1:通过LoadingEntityEntry获取原始加载状态

如果坚持使用PreLoadEventListener,可以从Session的加载上下文中获取LoadingEntityEntry,从中拿到数据库加载的原始值:

@Component
public class EncryptionListener implements PreInsertEventListener, PreUpdateEventListener, PreLoadEventListener {
    ...
    @Override
    public void onPreLoad(PreLoadEvent event) {
        Object entity = event.getEntity();
        Session session = event.getSession();
        
        // 获取加载中的实体条目,拿到原始状态
        LoadingEntityEntry loadingEntry = session.getLoadContexts()
                .findLoadingEntityEntry(session.getEntityKey(entity));
        
        if (loadingEntry != null) {
            Object[] loadedState = loadingEntry.getLoadedState();
            String[] propertyNames = event.getPersister().getPropertyNames();
            fieldDecrypter.decrypt(loadedState, propertyNames, entity);
        }
    }
}

方案2:改用AttributeConverter(推荐)

Hibernate官方更推荐使用AttributeConverter处理字段级加密解密,这种方式更简洁,且天然兼容Hibernate 6.x:

  1. 创建加密转换类:
@Converter(autoApply = true) // autoApply=true会自动应用到所有String类型字段,也可单独在字段上标注
public class EncryptionConverter implements AttributeConverter<String, String> {

    private final Encryptor encryptor; // 注入自定义加密工具类

    // 构造器注入加密工具
    public EncryptionConverter(Encryptor encryptor) {
        this.encryptor = encryptor;
    }

    // 实体字段转数据库存储值(加密)
    @Override
    public String convertToDatabaseColumn(String attribute) {
        return attribute == null ? null : encryptor.encrypt(attribute);
    }

    // 数据库值转实体字段(解密)
    @Override
    public String convertToEntityAttribute(String dbData) {
        return dbData == null ? null : encryptor.decrypt(dbData);
    }
}
  1. 在实体字段上应用(若未设置autoApply=true):
@Entity
@ToString
public class Phone {
    @Id
    private UUID id;
    
    @Convert(converter = EncryptionConverter.class)
    private String phoneNumber;
    
    @Convert(converter = EncryptionConverter.class)
    private String address;
    
    // getter、setter、无参构造方法
}

这种方式无需手动注册EventListener,Hibernate会在字段读写时自动触发加密解密逻辑,代码更易维护。

内容的提问来源于stack exchange,提问作者bonjugi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 10:33:17