2017-06-16 1 views
1

In meiner Java-App verwende ich Hibernate Envers, um auf persistente Ereignisse zu warten. Meine Hörerklasse sieht so aus.Hibernate Envers: Es ist ein Assertionsfehler aufgetreten (dies könnte auf einen Fehler in Hibernate hinweisen, liegt aber wahrscheinlich an der unsachgemäßen Verwendung der Sitzung)

@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 
     } 
    } 

} 

Im fromDAO Verfahren konvertiert die I DAO (Entitätstyp) Objekt zu einem Objekt api-Typs. Dies ist die fromDAO Methode

@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; 
    } 

Fehler tritt auf, wenn getCountryFromId(data.getId())

Diese Methode beinhaltet eine Spring Data JPA-Repository Aufruf zu tun, wo der Fehler auftritt. Der Repository Aufruf sieht wie folgt aus

repository.findByCountry_Id(dataId); 

Beim Debuggen ich sehe, dass dataID einen nicht Null-Wert hat, Repository ist nicht null, und die Abfrage sollte ein gültiges Ergebnis. Aber irgendwie tritt dieser Fehler auf

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) 

Ist es, weil ich eine Frage von ithe onPostInsert Methode mache? Ist eine Abfrage von dieser Methode nicht sicher? Ich sehe kein Problem in den Daten, meine Ahnung ist, dass es etwas mit Hibernate Envers zu tun hat, aber ich kann nicht herausfinden. Kann mir bitte jemand auf die richtige Weise zeigen. Vielen Dank !!

Antwort

1

Liegt es daran, dass ich eine Abfrage von der onPostInsert-Methode mache?

Wahrscheinlich. Von dem, was ich sehe, wurde ein vorheriger Flush von der Abfrage ausgelöst.
Wahrscheinlich verwenden Sie generierte Hibernate-IDs (am wahrscheinlichsten db generiert).

Ist eine Abfrage von dieser Methode nicht sicher?

Je nach spezifischem Fall könnte unsicher sein.
Sicher bricht es Massen/Batch-Einsätze, stark verschlechternde Leistung.

Versuchen Sie, die aktuelle Transaktion zu unterbrechen, um das Leeren zu verhindern und die Abfrage außerhalb auszuführen.
Sie können veraltete Ergebnisse erhalten, aber das scheint in diesem Fall kein Problem zu sein.

Sie nicht wissen, wie es im Frühjahr zu tun, in JavaEE Sie ein EJB-Methode wie aufrufen können:

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) // alternatively use REQUIRES_NEW 
public Country getCountryFromId(Object id) { 
    .... 
} 

Ich bin sicher, dass eine Feder Äquivalent gibt.

Ich sehe kein Problem in den Daten, meine Ahnung ist, dass es etwas mit Hibernate Envers zu tun hat, aber ich kann nicht herausfinden.

Es gibt ein Problem in den Daten: Die ID ist null - wurde noch nicht zugewiesen.
Ich verwende von Anwendungen generierte IDs (in der Regel UUID oder SUID), um diese Kategorie von Problemen zu vermeiden.

Envers führt seine Prüfung auch auf einem Listener aus, aber es gibt keine Beweise in der ST und wir wissen nicht, welcher Listener zuerst ausgeführt wird - Ihr oder Envers.

In beiden Fällen scheint dies unabhängig voneinander. Ich würde zuerst andere Dinge überprüfen (Auto-Flush verhindern).

+0

Danke für die Antwort. Ich verstehe nicht alle Details in Ihrer Antwort, aber von dem, was ich verstehen konnte, entschied ich mich für mehr Debugging. Ich habe festgestellt, dass beim Abfeuern des Listeners das DataDAO-Objekt zu diesem Zeitpunkt nicht in der Datenbank gespeichert wird. Mit dem Namen onPostInsert ging ich davon aus, dass dies ausgelöst würde, wenn die Einfügung in die db gemacht wurde. Irgendeine Idee, wie ich das Objekt sichern kann, wird gespeichert, bevor ich die Abfrage mache? Auch konnte ich nicht verstehen, wie der Flush den Fehler verursacht. Kannst du bitte kurz erklären. Vielen Dank !! – varunkr

+0

Endlich konnte ich mit PersistEventListener erreichen, was ich wollte. Vielen Dank !! – varunkr

+1

Ich bin froh, dass du es geschafft hast. Lesen Sie, wie Persistenz-Provider (Hibernate) die Datenbanksynchronisierung abwickeln, da Persistenzen einer Entität nicht sofort in eine SQL-Insert-Anweisung umgesetzt werden. SQL-Anweisungen wie Einfügen, Aktualisieren und Löschen werden nur für * flush * ausgegeben. Und der * Flush * kann manuell ausgelöst werden, d. H. Unter Verwendung von 'EntityManager.flush' oder automatisch, d. H. Wenn Sie eine Abfrage in derselben Transaktion durchführen. –

Verwandte Themen