2017-07-29 2 views
0

ich ein Stück Beispielcode haben:Transaktion Rollback in JPA funktioniert nie

public class JpaTest { 
    private EntityManagerFactory emf; 

    private void setUp() throws Exception { 
     emf = Persistence.createEntityManagerFactory("testPU"); 
    } 

    private void tearDown() { 
     emf.close(); 
    } 

    private void save() { 
     EntityManager em = null; 
     EntityTransaction tx = null; 
     try { 
      em = emf.createEntityManager(); 
      tx = em.getTransaction(); 
      tx.begin(); 
      em.persist(new Event("First event", new Date())); 
      em.persist(new Event("A follow up event", new Date())); 
      throw new RuntimeException(); 
     } catch (Exception e) { 
      if (tx != null) tx.rollback(); 
     } finally { 
      if (em != null) em.close(); 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     JpaTest test = new JpaTest(); 
     test.setUp(); 
     test.save(); 
     test.tearDown(); 
    } 
} 

Die Datenbank ist MySQL. Der Code hält die Event-Entität in der Datenbank und löst dann eine Exception aus. Ich erwarte, dass tx.rollback(), um die Änderungen zu löschen in der Datenbank vorgenommen, aber dieser Befehl funktioniert nie und bleiben die Daten in der Tabelle:

enter image description here

Die Frage ist, warum tx.rollback() fehlschlägt und wie um Änderungen in der Datenbank zu löschen, wenn die Transaktion eine Ausnahme auslöst?

AKTUALISIERT: persistence.xml:

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence 
      http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" 
      version="2.1"> 

    <persistence-unit name="testPU"> 

     <class>exampleForTestingJpa.Event</class> 

     <properties> 
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> 
      <property name="javax.persistence.jdbc.url" 
         value="url here..."/> 
      <property name="javax.persistence.jdbc.user" value="username here..."/> 
      <property name="javax.persistence.jdbc.password" value="password here..."/> 

      <property name="hibernate.show_sql" value="true"/> 
      <property name="hibernate.hbm2ddl.auto" value="update"/> 
      <property name="hibernate.connection.autocommit" value="false"/> 
     </properties> 
    </persistence-unit> 
</persistence> 

pom.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>groupId</groupId> 
    <artifactId>example</artifactId> 
    <version>1.0-SNAPSHOT</version> 

    <build> 
     <plugins> 
      <plugin> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <version>3.1</version> 
       <configuration> 
        <source>1.8</source> 
        <target>1.8</target> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-orm</artifactId> 
      <version>4.3.8.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core</artifactId> 
      <version>5.2.9.Final</version> 
     </dependency> 
     <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>5.1.39</version> 
     </dependency> 
    </dependencies> 

</project> 
+0

Ich habe eine Frage.Was ist mit 'commit' in' finally' block? Ich denke, dass Sie es auch brauchen – fg78nc

+0

, wenn Ihr JPA-Anbieter wirklich eine Transaktion nicht zurücksetzt (und Sie nicht einige seltsame Konfiguration haben, die dies verursacht), dann ist das ein Fehler in Ihrem JPA-Anbieter. Kein JPA-Anbieter sollte standardmäßig "Autocommit" aktiviert haben, da dies gegen die JPA-Spezifikation –

+0

verstoßen würde Versuchen Sie, Ihr Projekt neu zu erstellen. Zeigen Sie Ihre pom.xml bitte – fg78nc

Antwort

1

Wie andere Benutzern sagen, es ist wahrscheinlich ein autocommit Problem, da nach dem MySQL documentation:

In InnoDB ... Standardmäßig startet MySQL die Sitzung für eac h neue Verbindung mit autocommit aktiviert, so MySQL eine commit nach jeder SQL-Anweisung, wenn diese Anweisung keinen Fehler zurückgegeben. Wenn eine Anweisung einen Fehler zurückgibt, hängt das Commit- oder Rollback-Verhalten vom Fehler ab. Siehe Abschnitt 14.21.4, "InnoDB-Fehlerbehandlung".

Außerdem sollten Sie das Objekt Transaction nicht in einer Variablen speichern.
Zu jeder Zeit, die Sie eine Transaction Methode aufrufen möchten, erhalten Sie das Transaction Objekt aus der EntityManager.

So ersetzen:

tx = em.getTransaction(); 
tx.begin(); 

von:

em.getTransaction().begin(); 

Und ersetzen tx.rollback(); durch em.getTransaction().rollback();

Die Transaction im EntityManager gespeicherte Objekt serialisiert sein können und haben so eine neue Referenz bei Transaktionsverarbeitung.

Zum Beispiel sehen Sie die Serialisierungsmethode von AbstractEntityManagerImpl:

public class org.hibernate.jpa.spi.AbstractEntityManagerImpl{ 
... 
    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 
    ois.defaultReadObject(); 
    tx = new TransactionImpl(this); 
    } 
... 
} 
+0

Ich habe diese Ersetzungen gemacht und in persistence.xml eingefügt, aber es hat nicht geholfen. Die Daten bleiben in der DB-Tabelle, Rollback hat keine Wirkung – sva605

+0

Haben Sie auch die Änderung mit 'em.getTransaction()' vorgenommen? – davidxxx

+0

Ja http://clip2net.com/s/3Mx7LYx – sva605

1

Fügen Sie diese auf Ihre persistence.xml

<property name="hibernate.connection.autocommit" value="false"/> 
+0

fg78nc hatte es vor mir –

1

Vielleicht autocommit aktiviert ist? Das Handbuch von MySQL gibt an, dass Autocommit standardmäßig aktiviert ist.

Wenn das das Problem ist, werden Sie sicherlich nicht der Erste sein, der darüber gestolpert ist ;-)

+0

Guter Punkt :) Ich fügte die offizielle Referenz in meiner Antwort – davidxxx

+0

Nun, das Handbuch zu konsultieren ist etwas, das ich dazu tendiere, die meiste Zeit zu vergessen, hehe. Aber hier geben wir natürlich gute Beispiele. –

+0

Das Ergebnis ist das gleiche, es hat nicht geholfen – sva605

Verwandte Themen