Hibernate 5 持久化并刷新以该实例结尾的实体在数据库中还不存在作为一行
Hibernate 5 persist and refresh an entity ends with this instance does not yet exist as a row in the database
我刚刚将 Hibnernate 从版本 3.3.1.GA 迁移到版本 5.3.3.Final。 Everythink 工作正常,除了一个 think。如果我保留一个实体,将其刷新并提交到数据库,那么该实体确实存在于数据库中(我用 select 语句检查了它)。但是如果我刷新这个实体。我收到以下异常:
Caused by: javax.persistence.EntityNotFoundException: No row with the given identifier exists: [this instance does not yet exist as a row in the database#14]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:133)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.fireRefresh(SessionImpl.java:1336)
at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1301)
at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1295)
at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:3625)
at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:3601)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.jboss.seam.persistence.EntityManagerInvocationHandler.invoke(EntityManagerInvocationHandler.java:46)
at com.sun.proxy.$Proxy131.refresh(Unknown Source)
at service.CustomEntityHome.refreshInstance(CustomEntityHome.java:410)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:77)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.transaction.TransactionInterceptor.work(TransactionInterceptor.java:97)
at org.jboss.seam.util.Work.workInTransaction(Work.java:61)
at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:91)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185)
at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103)
at service.AnredeHome_$$_javassist_seam_46.refreshInstance(AnredeHome_$$_javassist_seam_46.java)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:335)
... 62 more
我调试了一下这里是Trace:
MutableEntityEntry(AbstractEntityEntry).getCompressedValue(AbstractEntityEntry$BooleanState) line: 516
MutableEntityEntry(AbstractEntityEntry).isExistsInDatabase() line: 228
DefaultRefreshEventListener.onRefresh(RefreshEvent, Map) line: 117
DefaultRefreshEventListener.onRefresh(RefreshEvent) line: 48
SessionImpl.fireRefresh(RefreshEvent) line: 1306
SessionImpl.refresh(Object) line: 1257
在第 516 行 MutableEntityEntry 中有一个 return 语句
return ( ( compressedState & state.getMask() ) >> state.getOffset() ) == 1;
变量是:
compressedState=17 == 0001 0001
(looking in the code)
(0001 the 4. positions means 4 - existsInDatabase ???)
(What does 17 mean ???)
state.getMask()=8192
state.getOffset()=13
所以==>
( ( 17 & 8192 ) >> 13 ) == 1
==> False
==> MutableEntityEntry(AbstractEntityEntry).isExistsInDatabase() line: 228 is false ???WHY???
==> in line 228 MutableEntityEntry
throw new UnresolvableObjectException(
e.getId(),
"this instance does not yet exist as a row in the database"
);
为什么压缩状态是17?它应该是什么,我该如何更改它?
PS:我正在使用 Java 10 和旧的 Framework Seam 2.2。2.Final 我现在无法升级它。
PPS:Seam 2.2.2 是针对 Hibernate 3 编译的,为了迁移到 Hibernate 5 我不得不扩展两个接口和一个 class,因为它们移动到不同的包中:
SessionImplementor
package org.hibernate.engine;
public interface SessionImplementor extends org.hibernate.engine.spi.SessionImplementor {}
事件源
package org.hibernate.event;
public interface EventSource extends org.hibernate.event.spi.EventSource {}
和 CustomHibernatePersistenceProvider
package org.jboss.seam.persistence;
import javax.persistence.EntityManager;
import org.hibernate.Session;
import org.hibernate.metadata.ClassMetadata;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
@Name("org.jboss.seam.persistence.persistenceProvider")
@Scope(ScopeType.STATELESS)
@BypassInterceptors
@Install(precedence = Install.APPLICATION, classDependencies = { "org.hibernate.Session",
"javax.persistence.EntityManager" })
public class CustomHibernatePersistenceProvider extends HibernatePersistenceProvider {
public static Object getVersion(final Object value, final Session session) {
ClassMetadata classMetadata = getClassMetadata(value, session);
return classMetadata != null && classMetadata.isVersioned() ? classMetadata.getVersion(value) : null;
}
private static ClassMetadata getClassMetadata(final Object value, final Session session) {
Class entityClass = getEntityClass(value);
ClassMetadata classMetadata = null;
if (entityClass != null) {
classMetadata = session.getSessionFactory().getClassMetadata(entityClass);
if (classMetadata == null) {
throw new IllegalArgumentException(
"Could not find ClassMetadata object for entity class: " + entityClass.getName());
}
}
return classMetadata;
}
@Override
public Object getVersion(final Object bean, final EntityManager entityManager) {
try {
return getVersion(bean, getSession(entityManager));
} catch (NotHibernateException nhe) {
return super.getVersion(bean, entityManager);
}
}
private Session getSession(final EntityManager entityManager) {
Object delegate = entityManager.getDelegate();
if (delegate instanceof Session) {
return (Session) delegate;
} else {
throw new NotHibernateException();
}
}
}
编辑:该错误已在 Hibernate 版本 5.3.8 中修复。和 5.4.1.!!!
Hibernate 版本 5.3.8 修复了该错误。和 5.4.1。 !!!
我刚刚将 Hibnernate 从版本 3.3.1.GA 迁移到版本 5.3.3.Final。 Everythink 工作正常,除了一个 think。如果我保留一个实体,将其刷新并提交到数据库,那么该实体确实存在于数据库中(我用 select 语句检查了它)。但是如果我刷新这个实体。我收到以下异常:
Caused by: javax.persistence.EntityNotFoundException: No row with the given identifier exists: [this instance does not yet exist as a row in the database#14]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:133)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.fireRefresh(SessionImpl.java:1336)
at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1301)
at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1295)
at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:3625)
at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:3601)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.jboss.seam.persistence.EntityManagerInvocationHandler.invoke(EntityManagerInvocationHandler.java:46)
at com.sun.proxy.$Proxy131.refresh(Unknown Source)
at service.CustomEntityHome.refreshInstance(CustomEntityHome.java:410)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:77)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.transaction.TransactionInterceptor.work(TransactionInterceptor.java:97)
at org.jboss.seam.util.Work.workInTransaction(Work.java:61)
at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:91)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185)
at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103)
at service.AnredeHome_$$_javassist_seam_46.refreshInstance(AnredeHome_$$_javassist_seam_46.java)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:335)
... 62 more
我调试了一下这里是Trace:
MutableEntityEntry(AbstractEntityEntry).getCompressedValue(AbstractEntityEntry$BooleanState) line: 516
MutableEntityEntry(AbstractEntityEntry).isExistsInDatabase() line: 228
DefaultRefreshEventListener.onRefresh(RefreshEvent, Map) line: 117
DefaultRefreshEventListener.onRefresh(RefreshEvent) line: 48
SessionImpl.fireRefresh(RefreshEvent) line: 1306
SessionImpl.refresh(Object) line: 1257
在第 516 行 MutableEntityEntry 中有一个 return 语句
return ( ( compressedState & state.getMask() ) >> state.getOffset() ) == 1;
变量是:
compressedState=17 == 0001 0001
(looking in the code)
(0001 the 4. positions means 4 - existsInDatabase ???)
(What does 17 mean ???)
state.getMask()=8192
state.getOffset()=13
所以==>
( ( 17 & 8192 ) >> 13 ) == 1
==> False
==> MutableEntityEntry(AbstractEntityEntry).isExistsInDatabase() line: 228 is false ???WHY???
==> in line 228 MutableEntityEntry
throw new UnresolvableObjectException(
e.getId(),
"this instance does not yet exist as a row in the database"
);
为什么压缩状态是17?它应该是什么,我该如何更改它?
PS:我正在使用 Java 10 和旧的 Framework Seam 2.2。2.Final 我现在无法升级它。 PPS:Seam 2.2.2 是针对 Hibernate 3 编译的,为了迁移到 Hibernate 5 我不得不扩展两个接口和一个 class,因为它们移动到不同的包中:
SessionImplementor
package org.hibernate.engine;
public interface SessionImplementor extends org.hibernate.engine.spi.SessionImplementor {}
事件源
package org.hibernate.event;
public interface EventSource extends org.hibernate.event.spi.EventSource {}
和 CustomHibernatePersistenceProvider
package org.jboss.seam.persistence;
import javax.persistence.EntityManager;
import org.hibernate.Session;
import org.hibernate.metadata.ClassMetadata;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
@Name("org.jboss.seam.persistence.persistenceProvider")
@Scope(ScopeType.STATELESS)
@BypassInterceptors
@Install(precedence = Install.APPLICATION, classDependencies = { "org.hibernate.Session",
"javax.persistence.EntityManager" })
public class CustomHibernatePersistenceProvider extends HibernatePersistenceProvider {
public static Object getVersion(final Object value, final Session session) {
ClassMetadata classMetadata = getClassMetadata(value, session);
return classMetadata != null && classMetadata.isVersioned() ? classMetadata.getVersion(value) : null;
}
private static ClassMetadata getClassMetadata(final Object value, final Session session) {
Class entityClass = getEntityClass(value);
ClassMetadata classMetadata = null;
if (entityClass != null) {
classMetadata = session.getSessionFactory().getClassMetadata(entityClass);
if (classMetadata == null) {
throw new IllegalArgumentException(
"Could not find ClassMetadata object for entity class: " + entityClass.getName());
}
}
return classMetadata;
}
@Override
public Object getVersion(final Object bean, final EntityManager entityManager) {
try {
return getVersion(bean, getSession(entityManager));
} catch (NotHibernateException nhe) {
return super.getVersion(bean, entityManager);
}
}
private Session getSession(final EntityManager entityManager) {
Object delegate = entityManager.getDelegate();
if (delegate instanceof Session) {
return (Session) delegate;
} else {
throw new NotHibernateException();
}
}
}
编辑:该错误已在 Hibernate 版本 5.3.8 中修复。和 5.4.1.!!!
Hibernate 版本 5.3.8 修复了该错误。和 5.4.1。 !!!