在我的java应用程序中,我使用Hibernate Envers来监听持久性事件。我的听众课看起来像这样。
@Component
public class DataCreationListener extends EnversPostInsertEventListenerImpl {
private static final long serialVersionUID = 1L;
@Autowired
DataService DataService;
public DataCreationListener() {
super(null);
}
@Override
public void onPostInsert(PostInsertEvent event) {
if (event.getEntity() instanceof DataDAO) {
Data Data = DataService.fromDao((DataDAO) event.getEntity());
// other stuff
}
}
}
在fromDAO
方法中,我将DAO
(实体类型)对象转换为api类型对象。这是fromDAO
方法
@Override
public Data fromDao(DataDAO data) {
if (data == null) {
return null;
}
Data api = new Data();
api.setId(data.getIdUser());
api.setAddress(data.getAddress());
api.setCity(data.getCity());
api.setCountry(getCountryFromId(data.getId()));
return api;
}
执行getCountryFromId(data.getId())
此方法涉及发生错误的Spring Data JPA存储库调用。存储库调用看起来像这样
repository.findByCountry_Id(dataId);
在调试时,我看到dataId具有非null值,repository非null,查询应该给出有效结果。但不知何故发生了这种错误
04:15:10.504 [http-nio-8080-exec-2] ERROR org.hibernate.AssertionFailure - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: null id in my.app.dbAccess.models.DataDAO entry (don't flush the Session after an exception occurs)
org.hibernate.AssertionFailure: null id in my.app.dbAccess.models.DataDAO entry (don't flush the Session after an exception occurs)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:60)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:175)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:135)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1251)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1319)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:606)
at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:529)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.count(SimpleJpaRepository.java:486)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:503)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:488)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:280)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy137.count(Unknown Source)
at my.app.dbAccess.generated.proxy.CountryRepositoryImpl.findByCountry_Id(CountryRepositoryImpl.java:800)
at my.app.services.DataServiceImpl.getCountryFromId(DataServiceImpl.java:131)
at my.app.services.DataServiceImpl.fromDao(DataServiceImpl.java:109)
at my.app.services.DataServiceImpl.fromDao(DataServiceImpl.java:1)
at my.app.services.DataServiceImpl.fromDao(DataServiceImpl.java:118)
at my.app.services.DataServiceImpl.fromDao(DataServiceImpl.java:1)
at my.app.services.DataServiceImpl$$FastClassBySpringCGLIB$$72be48ea.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:651)
at my.app.services.DataServiceImpl$$EnhancerBySpringCGLIB$$c0525c49.fromDao(<generated>)
at my.app.event.consumers.DataCreationListener.onPostInsert(DataCreationListener.java:40)
at org.hibernate.action.internal.EntityIdentityInsertAction.postInsert(EntityIdentityInsertAction.java:156)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:102)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:597)
是不是因为我正在使用onPostInsert方法进行查询?从这种方法做查询不安全吗?我没有看到数据有任何问题,我的预感是它与hibernate envers有关,但我无法弄清楚。有人可以用正确的方式指出我。谢谢!!
答案 0 :(得分:2)
是因为我正在使用onPostInsert方法进行查询吗?
可能的。从我看到的,从查询中触发了预先刷新。
您更有可能使用Hibernate生成的ID(很可能是生成的数据库)。
使用此方法进行查询是不安全的?
根据具体情况,可能不安全。
当然,它会破坏批量/批量插入,从而严重降低性能。
尝试暂停当前事务以防止刷新并在外部执行查询。
您可能会得到过时的结果,但在这种情况下这似乎不是问题。
在Spring中不知道怎么做,在JavaEE中你可以调用像EJB这样的方法:
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) // alternatively use REQUIRES_NEW
public Country getCountryFromId(Object id) {
....
}
我确定有一个等效弹簧。
我没有看到数据有任何问题,我的预感是它与hibernate envers有关,但我无法弄明白。
数据存在问题:ID为空 - 尚未分配。
我使用应用程序生成的ID(通常是UUID或SUID)来避免这类问题。
Envers也会对侦听器执行审计,但是ST中没有证据,我们没有首先运行哪个侦听器 - 你的或者Envers。
在这两种情况下,这似乎都无关紧要。我先检查其他事情(防止自动冲洗)。