Hibernate字节码增强:如何让已查询属性自动赋值到实体对应字段?
可行解决方案
针对Hibernate 5.3.15 + JBoss EAP 7.2.8的场景,有两种不需要手动调用getter的实现方式:
方案1:配置Hibernate字节码增强同步参数
你可以直接在项目的persistence.xml的Hibernate属性配置段新增以下配置:
<property name="hibernate.enhancer.enableDirtyTracking" value="true"/> <property name="hibernate.enhancer.enableLazyInitialization" value="true"/> <property name="hibernate.enhancer.enableAssociationManagement" value="true"/> <!-- 核心配置:实体加载完成后自动将已查询属性写入对应字段 --> <property name="hibernate.applyToEntityLoads" value="true"/>
开启该配置后,Hibernate在实体加载完成(包括JPQL查询返回实体)时,会自动把所有已加载的属性值同步到实体的对应字段,不需要主动触发getter调用。
方案2:调用Hibernate内置工具批量同步属性
如果方案1的配置不生效(部分JBoss EAP的内置Hibernate补丁会覆盖自定义的字节码增强配置),可以在EJB服务返回实体前,调用Hibernate官方提供的工具方法完成字段同步:
// 导入Hibernate核心类 import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.engine.spi.PersistentAttributeInterceptor; // 服务方法返回实体前执行 if (targetEntity instanceof PersistentAttributeInterceptable) { PersistentAttributeInterceptor interceptor = ((PersistentAttributeInterceptable) targetEntity).$$_hibernate_getInterceptor(); if (interceptor != null) { // 遍历所有已加载的属性写入实体字段 for (String attrName : interceptor.getLoadedAttributeNames()) { interceptor.readObject(targetEntity, attrName, null); } } }
该方法的效果和手动调用所有属性的getter一致,但不需要硬编码每个属性的getter调用,适配实体字段迭代的场景。
注意事项
- 不要在EJB服务层直接返回Hibernate代理对象,如果你同时开启了实体类的序列化代理配置,需要先调用
Hibernate.unproxy()把代理转换为实际实体对象再返回,避免RMI序列化时报错。 - JBoss EAP 7.2内置的Hibernate模块默认会关闭部分字节码增强特性,如果你是依赖JBoss内置的Hibernate模块而非将Hibernate打包到应用内,需要在
jboss-deployment-structure.xml中排除内置的Hibernate模块,使用自己打包的对应版本Hibernate依赖,配置才会生效。
内容的提问来源于stack exchange,提问作者Warren Nocos
相关产品推荐
相关产品推荐

