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:
- 创建加密转换类:
@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); } }
- 在实体字段上应用(若未设置
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
相关产品推荐
相关产品推荐

