英文:
Hibernate 5.3+ using hibernateLazyInitializer causes javax.persistence.EntityNotFoundException: Unable to find entity.Person
问题
在升级 Hibernate 到 5.3+ 版本时,使用 getHibernateLazyInitializer().getIdentifier()
方法来获取 HibernateProxy
上的标识符时遇到了问题,这个 HibernateProxy
是由 Hibernate Envers 的 AuditedReader
加载的。
以下是您提供的代码示例:
@Entity
@Audited
public class Person {
@Id
private Long id;
@Column(name="surname")
private String name;
@JoinColumn(name="country_id", foreignKey = @javax.persistence.ForeignKey(name="FK_country_id"))
@ManyToOne(cascade = { CascadeType.REFRESH }, fetch = FetchType.EAGER)
@Fetch(FetchMode.SELECT)
private Country country;
}
@Entity
@Audited
public class Country {
@Id
public Long id;
@Column(name="countryName")
public String countryName;
}
// 另一个类中的代码,我想从 Hibernate Envers 的 Person 表中获取 Country 的 ID
// field 是需要从对象中获取的变量的反射
// field = "country",需要从 personObject 中获取
private static Object getId(Object personObject, Field field) throws IllegalAccessException {
Object countryObject = field.get(personObject);
if (countryObject instanceof HibernateProxy) {
return ((HibernateProxy)countryObject).getHibernateLazyInitializer().getIdentifier();
}
return null;
}
使用上述代码时,您得到的堆栈跟踪如下:
javax.persistence.EntityNotFoundException: Unable to find entity.Country with id 10
at org.hibernate@5.3.29.Final-redhat-00001//org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:163)
at org.hibernate@5.3.29.Final-redhat-00001//org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:291)
at org.hibernate@5.3.29.Final-redhat-00001//org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:186)
at org.hibernate@5.3.29.Final-redhat-00001//org.hibernate.proxy.AbstractLazyInitializer.getIdentifier(AbstractLazyInitializer.java:95)
从堆栈跟踪来看,它表明找不到 ID 为 10 的 entity.Country
。尽管数据库中存在该国家的条目,但在不调试的情况下运行时会引发 EntityNotFoundException
。
您已经尝试升级 Hibernate 到更高版本,但似乎没有解决问题。可能需要检查以下方向或解决方案:
-
事务管理: 确保在查询数据库时使用适当的事务管理。有时,事务不会正确配置,导致无法找到实体。
-
缓存: 如果启用了缓存,尝试清除缓存并重新运行代码,看看是否有所帮助。
-
Auditing配置: 确保您的 Hibernate Envers 配置正确。可能需要检查 Envers 的版本与 Hibernate 版本的兼容性,并确保在审计表中正确记录了实体的更改。
-
日志: 使用日志来详细了解在代码执行期间发生了什么。这可能有助于确定问题所在。
-
Hibernate 和 JBoss 版本: 确保所使用的 Hibernate 和 JBoss 版本与您的代码和配置兼容。有时,特定版本之间可能存在问题或不兼容性。
请根据这些方向尝试查找问题的解决方案。如果问题仍然存在,您可能需要深入调查或考虑向 Hibernate 或 JBoss 社区寻求支持。
英文:
Having a problem with upgrading hibernate to 5.3+ with the method calling getHibernateLazyInitializer().getIdentifier()
on a HibernateProxy
which is loaded with AuditedReader
from hibernate envers.
The following example is what I have in code:
@Entity
@Audited
public class Person {
@Id
private Long id;
@Column(name="surname")
private String name;
@JoinColumn(name="country_id", foreignKey =
@javax.persistence.ForeignKey(name="FK_country_id"))
@ManyToOne(cascade = { CascadeType.REFRESH }, fetch = FetchType.EAGER)
@Fetch(FetchMode.SELECT)
private Country country;
}
@Entity
@Audited
public class Country {
@Id
public Long id;
@Column(name="countryName")
public String countryName;
}
/// Code in another class which I want to get the ID of the country from the Person that comes from the Audited Table of hibernate envers
/// The field is a reflection of which variable it needs to get out of the object
/// field = "country" which needs to get from the personObject
private static Object getId(Object personObject, Field field) throws IllegalAccessException {
Object countryObject = field.get(value);
if (object instanceof HibernateProxy) {
return ((HibernateProxy)countryObject).getHibernateLazyInitializer().getIdentifier();
}
return null;
}
The stacktrace which I get using the code is:
javax.persistence.EntityNotFoundException: Unable to find entity.Country with id 10
at org.hibernate@5.3.29.Final-redhat-00001//org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:163)
at org.hibernate@5.3.29.Final-redhat-00001//org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:291)
at org.hibernate@5.3.29.Final-redhat-00001//org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:186)
at org.hibernate@5.3.29.Final-redhat-00001//org.hibernate.proxy.AbstractLazyInitializer.getIdentifier(AbstractLazyInitializer.java:95)
The entry of the country is in the database so it exist, also when I debug with Intellij and evaluate the ((HibernateProxy)countryObject).getHibernateLazyInitializer()
, it will return the object but if I let it run without debug I'll get EntityNotFoundException
.
Already spended hours to figure how to fix it, even upgrading hibernate to a higher version but it doesn't seems to fix it. Someone knows in which direction or solution I can look at.
Thanks
PS: We are using the JBoss 7.4 EAP with patch 11, so using all of their dependencies (the important usage for this code is hibernate-core-5.3.29.Final-redhat-00001
and hibernate-envers-5.3.28.Final-redhat-000015.3.28.Final-redhat-00001
also using javax.persistence.api
).
答案1
得分: 1
今天我解决了这个问题,我们从 Hibernate 3.x 升级到 Hibernate 5.x,((HibernateProxy)countryObject).getHibernateLazyInitializer().getIdentifier()
这个方法发生了变化。在 Hibernate 3.x 中,它直接返回对象的标识符,但在 Hibernate 5.x 中,当你调用这个方法时,它会初始化对象,从而引发了未找到异常。
// 来自 org.hibernate.proxy.AbstractLazyInitializer Hibernate 5.x
@Override
public final Serializable getIdentifier() {
if ( isUninitialized() && isInitializeProxyWhenAccessingIdentifier() ) {
initialize(); // <-- 这导致了实体未找到异常
}
return id;
}
因此,为了解决这个问题,我们使用了
((HibernateProxy)countryObject).getHibernateLazyInitializer().getInternalIdentifier()
,它只返回标识符而不初始化对象,因为我们只需要标识符。
英文:
Today I have solved the issue, We went from hibernate 3.x to hibernate 5.x and there was a change in the ((HibernateProxy)countryObject).getHibernateLazyInitializer().getIdentifier()
. The hibernate 3.x returns directly the id of the object but in hibernate 5.x when you call this method it will initialize the object which cause the not found exception.
// from org.hibernate.proxy.AbstractLazyInitializer hibernate 5.x
@Override
public final Serializable getIdentifier() {
if ( isUninitialized() && isInitializeProxyWhenAccessingIdentifier() ) {
initialize(); // <-- this causes the entity not found exception
}
return id;
}
So to fix this we used
((HibernateProxy)countryObject).getHibernateLazyInitializer().getInternalIdentifier()
which only returns the id and not initialize the object because we only needed the Id.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论