2016-08-12 2 views
1

Ich habe diese lästige Ausnahme beim Versuch, eine native Abfrage mit meinem Entity Manager zu erstellen. Die vollständige Fehlermeldung lautet:IllegalStateException beim Versuch, NativeQuery mit EntityManager zu erstellen

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: [email protected] 
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:313) 
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:723) 
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:441) 
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:874) 
at org.eclipse.persistence.internal.jpa.QueryImpl.performPreQueryFlush(QueryImpl.java:967) 
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:207) 
at org.eclipse.persistence.internal.jpa.QueryImpl.getSingleResult(QueryImpl.java:521) 
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:400) 

Der eigentliche Code, der den Fehler auslöst, ist:

Query query; 
    query = entityManager.createNativeQuery(
      "SELECT MAX(CAST(SUBSTRING_INDEX(RecordID,'-',-1) as Decimal)) FROM `QueriedEntityTable`"); 
    String recordID = (query.getSingleResult() == null ? 
      null : 
      query.getSingleResult() 
       .toString()); 

Dieses im doTransaction Teil mit einem EntityTransaction ausgeführt wird. Der Teil, der mich mit diesem obwohl bekommt ist, dass dies der erste Code innerhalb des doTransaction Methode ausgeführt werden, vereinfacht unten an:

updateOneToManyEntity1(); 
updateOneToManyEntity2(); 
entityManager.merge(parentEntity); 

Das Unternehmen hat ein Problem mit „OneToManyEntity1“ ist nicht einmal die Tabelle Ich versuche, die Abfrage zu erstellen. Ich bleibe auch nicht bestehen oder bis zu diesem Punkt zusammenführen, so dass ich auch nicht sicher bin, was angeblich dazu führt, dass es nicht synchron ist. Die einzige Datenbankarbeit, die bis zur Ausführung dieses Codes ausgeführt wird, besteht darin, Daten einfach einzuziehen und nichts zu ändern. Die Fremdschlüssel sind ordnungsgemäß in der Datenbank eingerichtet.

Ich bin in der Lage, diesen Fehler loszuwerden, indem Sie tun, wie es sagt und diese Beziehungen als Cascade.PERSIST markieren, aber dann bekomme ich eine MySQLContrainstraViolationException in der query.getSingleResult() -Zeile. Meine Protokolle zeigen, dass einige INSERT-Abfragen direkt davor ausgeführt werden. Daher sieht es so aus, als ob sie den EntityManager.merge-Teil meiner doTransaction-Methode erreichen, aber der Fehler und der Aufrufstack zeigen auf einen völlig anderen Teil des Codes.

Verwenden von EclipseLink (2.6.1), Glassfish 4 und MySQL. Der EntityManager verwendet RESOURCE_LOCAL mit allen erforderlichen Klassen, die unter dem Persistence-Unit-Tag aufgelistet sind, und exclude-nichtlisted-classes wird auf false gesetzt.

Edit: So ein paar mehr Informationen, wie ich versuche, durch diese zu arbeiten. Wenn ich einen Breakpoint am Anfang der Transaktion setze und dann entityManager.clear() über IntelliJs "Evaluate Expression" -Werkzeug ausfühle, funktioniert alles mindestens beim ersten Mal gut. Ohne es bekomme ich einen Fehler, wie es versucht, leere Objekte in die Tabelle einzufügen.

Edit # 2: Ich konvertierte den nativeQuery-Teil in die Criteria-API und ließ mich meinen Code durcharbeiten, so dass ich herausfinden konnte, wo er unbeabsichtigt ein NULL-Objekt zu meiner Entity-Liste hinzugefügt hat. Ich bin immer noch verwirrt, warum der Entity Manager diese Fehler oder so etwas zwischenspeichert, dass das Erstellen einer systemeigenen Abfrage nicht funktioniert, weil sie immer noch versucht, fehlerhafte Daten einzufügen. Ist das etwas, das ich EntityManager.clear() aufrufen müsste, bevor ich es jedes Mal mache? Oder soll ich das aufrufen, wenn die doTransaction-Methode fehlerhaft ist?

+0

Wo haben Sie die Transaktionsgrenze platziert? –

+0

Ich versuche, das jetzt zu lesen. Ich bin mir nicht sicher, ob ich es eingestellt habe oder ich verstehe das Konzept falsch. Ich bekomme eine Transaktion vom Entity Manager mit EntityManager.getTransaction() und dann Aufruf von .begin(), .doTransaction(), und dann .committ() bei Erfolg oder. Rollback() für Fehler. Da es sich um einen Resource_Local-Persistenzkontext handelt, glaube ich nicht, dass ich es brauche? – gdawgrancid

Antwort

0

Nachdem ich den Code überarbeitet und beiseite gelegt hatte, stolperte ich über zumindest einen Teil der Antwort auf meine Frage. Mein Problem wurde dadurch verursacht, dass das Objekt vor dem Start der Transaktion beibehalten wurde. Als ich meine Transaktion eingab, versuchte sie zuerst, Daten von meinen Entitätsobjekten einzufügen/zu aktualisieren, und warf einen Fehler, da ich die Werte der meisten Nicht-Null-Spalten nicht gesetzt hatte. Ich glaube, das ist der Grund, warum ich die Kaskadenfehler erhielt, und ich bin sicher, dass dies die Quelle der zufälligen Einfügeabfragen ist, die ich zu Beginn meiner Transaktion abgefeuert habe. Hoffe, das hilft einem anderen, eine Menge Ärger zu vermeiden.

Verwandte Themen