MySQL Transaktionen in Entity-Class

derFabi95

Mitglied
Hallo alle zusammen,
aktuell beschäftige ich mich ein wenig mit JPA (EclipseLink). Jetzt stoße ich auf ein Problem in den Abhängigkeiten.
Ich demonstriere das mal in einem Beispiel:
Java:
public class Update {
    
    Spieler spieler = new Spieler("Testspieler");
    
    public static void main(String[] args) {
        settings.setProperty("javax.persistence.schema-generation.database.action", "create");
        emfactory = Persistence.createEntityManagerFactory("MeinePU", settings);
        em = emfactory.createEntityManager();

        em.getTransaction().begin();
        
        Spiel spiel = em.find(Spiel.class, 1);
        spiel.beitreten(spieler);
        em.persist(spiel);

        em.getTransaction().commit();
        
        em.close();
        emfactory.close();
    }
}
Code:
@Entity
public class Spiel {
    @Id
    private int id;
    @OneToMany(mappedBy = "spiel")
    private List<Spieler> spieler;
    
    public Spiel(int id) {
        this.id = id;
    }

    public Spiel() {
        this.id = 0;
    }
    
    public List<Spieler> getSpieler() {
        return spieler;
    }
    
    public void beitreten(Spieler spieler) {
        getSpieler().add(spieler);
    }
}
Code:
@Entity
public class Spieler {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column(length = 25)
    private String name;
    @ManyToOne
    private Spiel spiel;
    
    public Spieler(String name) {
        this.name = name;
    }
    
    public Spieler() {
        this.name = "Testspieler";
    }
}

Mein Problem ist, ich möchte über meine Update.class einen Spieler für ein Spiel hinzufügen. Jedoch bekomme ich jedes Mal eine Fehlermeldung, es gäbe nichts zu commiten. Muss ich den EntityManager im Konstruktor an "Spiel" weitergeben und dort die Transaction machen, wenn "beitreten" aufgerufen wird?
Danke allen schon mal!
 

mihe7

Top Contributor
Wie sieht denn Deine persistence.xml aus?

Nachtrag: unabhängig davon dürfte das, was Du da machst, nicht funktionieren. Mit persist werden neue Objekte hinzugefügt, Spiel hast Du bereits aus der DB geladen.
 
Zuletzt bearbeitet:

derFabi95

Mitglied
Wie sieht denn Deine persistence.xml aus?

Nachtrag: unabhängig davon dürfte das, was Du da machst, nicht funktionieren. Mit persist werden neue Objekte hinzugefügt, Spiel hast Du bereits aus der DB geladen.
Wird also durch den reinen Aufruf von "beitreten" das direkt geupdatet, wenn es commited wird?

Die Persistence funktioniert... aber hier, bitte ;)
XML:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
    <persistence-unit name="MeinePU" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>de.JohnHSmith.RHFactions.Faction</class>
        <class>de.JohnHSmith.RHFactions.Player</class>
        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/rhfactions"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.schema-generation.database.action" value="create"/>
            <property name="javax.persistence.schema-generation.scripts.action" value="create"/>
            <property name="eclipselink.ddl-generation" value="create-tables"/>
        </properties>
    </persistence-unit>
</persistence>
 

mihe7

Top Contributor
Heißen Deine Entities jetzt Spiel und Spieler oder Game und Faction?

Die Persistence funktioniert..
Ich will ja nur sicher gehen...

Wird also durch den reinen Aufruf von "beitreten" das direkt geupdatet, wenn es commited wird?
Jein. Wenn eine Entity vom EntityManager gemanaged wird, dann werden Änderungen an der Entity registriert und zu bestimmten Zeitpunkten weggeschrieben.

Dabei muss man bei Beziehungen aufpassen, denn es ist ein Unterschied zwischen der Entity selbst und der Beziehung zu dieser Entity.

Würdest Du in dem Beispiel oben einfach das persist weglassen, würde folgendes passieren:
1. es wird ein neues Spieler-Objekt erzeugt, von dem der EntityManager keine Kenntnis hat. Aus sich des EntityManagers hat ein solches Objekt den Status NEW.
2. das Spiel wird aus der DB gelesen und ist im MANAGED-State.
3. das Spieler-Objekt wird zur Liste spieler der Spiel-Entity hinzugefügt.

Da die Spiel-Entity geändert wurde, würde der EntityManager versuchen, die Änderungen wegzuschreiben. Dabei stößt er auf die Spieler-Entity, die sich im NEW-State befindet und quittiert dies mit einem Fehler.

Du könntest also hergehen, und den Spieler vorher per persist wegschreiben. Dann nämlich befindet sich der Spieler ebenfalls im MANAGED-State und für den EntityManager wäre alles in Ordnung. Alternativ zum expliziten Aufruf von persist kannst Du auch angeben, dass der EntityManager neue Entities in der Beziehung automatisch persistieren soll. Dazu fügst Du der OneToMany-Annotation ein "cascade=CascadeType.PERSIST" hinzu.
 

derFabi95

Mitglied
Ah sorry, hab vergessen in der persistence.xml die Klassen umzubenennen für das Beispiel.
Ich probier mal noch ein bisschen rum, sollte dann ja klappen ;)
 

derFabi95

Mitglied
Hallo,
ich habe jetzt folgendes versucht:
Code:
public class Update {
   
    public static void main(String[] args) {
        settings.setProperty("javax.persistence.schema-generation.database.action", "create");
        emfactory = Persistence.createEntityManagerFactory("MeinePU", settings);
        em = emfactory.createEntityManager();

        em.getTransaction().begin();
       
        Spiel spiel = em.find(Spiel.class, 1);
        Spieler spieler = new Spieler("Testspieler");
        em.persist(spieler);
        spiel.beitreten(spieler);

        em.getTransaction().commit();
       
        em.close();
        emfactory.close();
    }
}
Allerdings heißt es immernoch, in der Transaction wäre nichts zu committen. Auch habe ich cascade auf Persist gestellt, jedoch passiert da auch nichts.
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Kannst Du mal ein kleines Beispiel zusammenschustern (am besten eines, das Maven verwendet), zippen und hier hochladen?

Das einzige, was meine Glaskugel noch hergibt, wäre dass Du die Spiel und/oder Spieler-Klasse in der persistence.xml nicht aufgeführt hast.
 

derFabi95

Mitglied
Kannst Du mal ein kleines Beispiel zusammenschustern (am besten eines, das Maven verwendet), zippen und hier hochladen?

Das einzige, was meine Glaskugel noch hergibt, wäre dass Du die Spiel und/oder Spieler-Klasse in der persistence.xml nicht aufgeführt hast.
Mit Maven hab ich bisher noch nicht gearbeitet....
Ich glaube, ich versuche hier zu weit advanced in JPA einzusteigen. Vielleicht gehen wir das ganze besser Schritt für Schritt an....
Ich lade mal was hoch, kannst du mir erklären wieso der Spieler zwar angelegt wird, jedoch als spiel-id (sollte ja ein FK sein) immer NULL eingetragen bekommt und nicht die tatsächliche Spiel-Nummer?
(Datei ist leider zu groß um sie hier hochzuladen, da die Libraries mit dabei sind... deshalb hier ein Dropbox-Link: https://www.dropbox.com/s/os6to7jechwdzfu/TestPersistence.zip?dl=0)
Danke schonmal für deine Hilfe!
 

thecain

Top Contributor
Ich vermute weil Getter und Setter in der Entity Klasse fehlt. Kann aber auch falsch liegen. Bin nicht so in den JPA internas...
 

mihe7

Top Contributor
kannst du mir erklären wieso der Spieler zwar angelegt wird, jedoch als spiel-id (sollte ja ein FK sein) immer NULL eingetragen bekommt und nicht die tatsächliche Spiel-Nummer?
Also wird ja doch etwas committed... Zur Frage: weil Du eine bidirektionale Beziehung definiert hast. Mit mappedBy gibst Du dabei das Attribut an, über das die Beziehung hergestellt wird. Du musst also auf der Spielerseite das Spiel angeben. Das kannst Du z. B. auch in der beitreten-Methode machen:
Java:
    public void beitreten(Spieler spieler) {
        getSpieler().add(spieler);
        spieler.setSpiel(this);
    }
Natürlich braucht die Spieler-Klasse einen entsprechenden Setter.
 

derFabi95

Mitglied
Also wird ja doch etwas committed...
Das war nur ein Beispiel-Code. Der lustigerweise auch funktioniert. In meinem echten Code habe ich jetzt mal folgendes gemacht:
Java:
Query query = em.createNamedQuery("Spieler.findByName");
query.setParameter("name", "Testspieler");
Spieler spieler = null;
if( !query.getResultList().isEmpty() ) {
    spieler = (Spieler) query.getSingleResult();
} else {
    spieler = new Spieler("Testspieler");
}
em.persist(spieler);

em.getTransaction().commit();
Ich bekomme trotz allem eine Fehlermeldung, dass keine Transaktion ausstehend wäre. Das ist doch nicht normal? In meinem Testprogramm läuft es auch... Aber da ich die Transaktion beginnen lasse, müsste er doch was finden!

EDIT:
Ich habe gerade herausgefunden, dass ich in der gleichen Main-Class weiter oben schon mal committed habe. Nachdem ich danach ein em.getTransaction().begin() eingefügt habe, ging es! Muss ich das jedesmal nach Committen neu beginnen?
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Ist das, was Du in der dropbox geschickt hast, nun irgendein Testcode, der funktioniert oder ist das "richtiger" Code, der nicht funktioniert?

Zum Schnipsel kann man wenig sagen (außer, dass das persist in den else-Zweig gehört).

Mach mal eine Kopie Deines Projekts und aus dem entfernst Du alles, was nicht benötigt wird, um den Fehler nachvollziehen zu können. Oft findet man dabei schon die Ursache des Problems. Wenn nicht, machst Du ein ZIP draus, lädst es hier hoch (die Bibliotheken kannst Du weglassen), damit sich das jemand aus dem Forum am lebenden Objekt nachvollziehen kann.
 

derFabi95

Mitglied
Ist das, was Du in der dropbox geschickt hast, nun irgendein Testcode, der funktioniert oder ist das "richtiger" Code, der nicht funktioniert?
Das ist ein Testcode.
Zum Schnipsel kann man wenig sagen (außer, dass das persist in den else-Zweig gehört).
Danke für den Hinweis!
Mach mal eine Kopie Deines Projekts und aus dem entfernst Du alles, was nicht benötigt wird, um den Fehler nachvollziehen zu können. Oft findet man dabei schon die Ursache des Problems. Wenn nicht, machst Du ein ZIP draus, lädst es hier hoch (die Bibliotheken kannst Du weglassen), damit sich das jemand aus dem Forum am lebenden Objekt nachvollziehen kann.
Genau das habe ich gemacht, weshalb ich den Fehler herausgefunden haben :) Danke!
 

derFabi95

Mitglied
Wie ich oben im Edit schon geschrieben hatte, ich hatte weiter oben im Code bereits committed und danach nicht mehr die Transaction neu begonnen. Offenbar muss man das jedes Mal machen, nachdem committed wurde.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
R Transaktionen von mehreren Anwendungen aus - JDBC Datenbankprogrammierung 3
D Geschachtelte Transaktionen in einem DBMS Datenbankprogrammierung 3
G PreparedStatement und Transaktionen Datenbankprogrammierung 2
J mal wieder eine Frage zu parallelen Transaktionen.. Datenbankprogrammierung 2
F Hibernate Transaktionen Datenbankprogrammierung 2
D mysql und transaktionen... Datenbankprogrammierung 8
torresbig MySQL hibernate - could not resolve entity class ... (Datenbank Anfänger) Datenbankprogrammierung 19
I Konzept: Klasse / Entity für Einstellung der Software Datenbankprogrammierung 3
J Netbeans 11 und Eclipse JPA 2.5 Entity wird nicht gefunden Datenbankprogrammierung 4
T Ebean Not an Entity Datenbankprogrammierung 1
V HSQLDB detached entity passed to persist: server.Employee Datenbankprogrammierung 4
H Entity in Java implementieren Datenbankprogrammierung 13
Y Entity must be managed to call remove Datenbankprogrammierung 1
F MySQL+ Netbeans: Datenbanken mit Automatisch generierten Entity Classes get und set Datenbankprogrammierung 2
T IllegalArgumentException: Person[ id=null ] is not a known entity type.??? Datenbankprogrammierung 0
R eclipselink - referenzierte Entity löschen Datenbankprogrammierung 0
Z ER Diagramm erstellen (Entity-Relationship) Datenbankprogrammierung 4
B Feld in einer @Entity als Text speichern Datenbankprogrammierung 5
K Entity-Klassen generieren Datenbankprogrammierung 4
D Datenbank Entity Datenbankprogrammierung 3
C Hibernate Liste mit allen Objekten einer Entity Datenbankprogrammierung 17
T org.hibernate.MappingException: entity class not found Datenbankprogrammierung 4
D org.hibernate.MappingException: Unknown entity mit Annotations Datenbankprogrammierung 9
P Hibernate -> SQL verwenden und keine Entity Datenbankprogrammierung 19
M Problem mit @Entity Datenbankprogrammierung 18
R JPA, Spring, löschen einer Entity Datenbankprogrammierung 2
P Neues Attribut in Entity-Klasse Datenbankprogrammierung 3
G Entity Realtionship Model erstellen Datenbankprogrammierung 11
QDog JPA: Entity "laden" und später updaten Datenbankprogrammierung 4
H Java Class zum komprimieren von Jpeg-Images zum Einbinden in Oracle DB - Bild als blob (in und out) Datenbankprogrammierung 23
S Table per Class Datenbankprogrammierung 2
temi Wie kann ich "Class" in einer DB speichern? Datenbankprogrammierung 2
T Hibernate und inner class Datenbankprogrammierung 0
P GWT Applikation-The method forName(String) is undefined for the type Class Datenbankprogrammierung 10
algebraiker Eclipse RCP - no persistent classes found for query class Datenbankprogrammierung 4
S MSSQL JDBC "Driver class not found" Datenbankprogrammierung 9
I MySQL MATLAB: Class.forName wirft ClassNotFoundException Datenbankprogrammierung 4
D MySQConnextor Class not found obwohl BuildPfad konfiguriert Datenbankprogrammierung 6
S Firebird NoClassDefFoundError trotz erfolgreichem Class.forName(...) unter Linux Datenbankprogrammierung 5
H Fat Jar Export: Could not find class-path entry for 'C:Java/jdk/mysql-connector-java- Datenbankprogrammierung 3
M ClassNotFoundException bei Class.forName(xx) Datenbankprogrammierung 6
N Class not found Exception Datenbankprogrammierung 2
B java.lang.Class.forName0(Native Method) Datenbankprogrammierung 3

Ähnliche Java Themen

Neue Themen


Oben