[Erledigt] Hibernate Verständnis Fragen/Probleme

Ich bin ja gerade dabei ein altes Projekt (meinen Musik Manager) auf Hibernate umzubauen, laden der Daten klappt auch super nur das speichern macht mir noch kleine Probleme.

Es gibt bei mir die Objekte Artist, Label, Genre, Album, CD, Track. Artist, Label, Genre sind einfache Objekte mit ID und Name, wobei ich gesagt hab das bei allen 3 der Name unique sein soll. Das Album ist etwas komplexer und enthält alle anderen Objekte.
Erzeugt werden die Objekte entweder von Hand, d.h. der Benutzer gibt die Daten ein bzw. wählt vorhandene aus oder es wird bei Amazon nach den Alben gesucht, wobei hier immer neue Objekte erzeugt werden.

Fügt man einen Datensatz komplett neu ein, wo noch kein Artist, Label … existiert klappt alles, fügt man aber ein Album neu hinzu, was schon einem Artist gehört gibts immer ne Exception. Seidenn ich ersetze diese doppelten Objekte durch ein bestehendes Objekt das aus der Datenbank geladen wurde.

Ich dachte das ich mit merge diese Daten automatisch aktualisieren lassen kann aber da hab ich mich wohl irgendwie geirrt. Daher meine Frage, kann ich das irgendwie von Hibernate machen lassen oder muss ich bevor ich speichere alle Daten von Hand setzen?

Hier mal die Fehlermeldung die nur kommt wenn der Artist, Label oder Genre schon existiert

Was willst du genau?? Von einem vorhandenen Objekt neue Werte setzen??

Das Hibernate merkt das dieses neue Objekt schon in der Datenbank ist und dementsprechend reagiert.

ja du bekommst eine exception auf die kannst du doch reagieren… wenn du willst dass er das neue Objekt entweder speichert oder updatet dann gibst die methode saveorupdate…

Die Methode gibt es bei mir nicht, ich arbeite mit dem EntetyManager der hat nur persist, find, merge, refresh und remove.

wenn du eine session hast kannst du diese methode anwenden…
http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html

Jo ich arbeite aber nicht mit Sessions :smiley:
Geht das nicht anders?

ich kenn nur den weg über sessions :wink:

Öhm, also bei mir hat das noch nie Probleme gemacht … Du hast das Objekt, das aktualisiert werden soll, aber schon aus der DB?

Mir ist immer noch nicht das Problem ganz klar. Kannst du mal ein textuelles Beispiel nennen wo das Problem auftreten würde?

Das ist ja das Problem, es stammt nicht aus der Datenbank :wink:
Die Objekte sind alle neu erzeugt.

Ich hab gerade nochmal rumgespielt aber nichts hinbekommen.

Also ich hab ein Objekt Album, das hat paar andere Objekte drin unter anderem Label. Das Label ist nur ne ID und nen Name, der Name ist unique, so dass er nur einmal vorhanden sein kann.
Jetzt erstelle ich neue Alben und die bekommen auch ein Label, aber es wird nicht ein Label aus der Datenbank geholt sondern ein neues Objekt erzeugt.

Jetzt würd ich Hibernate gern sagen das es nachsehen soll ob dieses Label schon in der Datenbank ist, wenn nicht einfügen. Ist es schon vorhanden sol ler das Objekt irgendwie so bearbeiten das er weiß das es die gleichen Einträge sind.

Ich habs jetzt erstmal so gelöst das ich immer nachseh ob der Eintrag schon vorhanden ist, wenn ja wird das schon geladene Objekt gekommen sonst aus der Datenbank.

Aber jetzt hab ich ein neues Problem, immer wieder bekomm ich diese Meldung wenn ich commit ausführen will.
hier der Code:

    EntityTransaction transaction = entitymanager.getTransaction();
    transaction.begin();
    try
    {
      for(Album album : albums)
      {
        System.out.println(transaction.isActive());
        entitymanager.merge(album);
        // entitymanager.persist(album);
      }

      transaction.commit();
    }
    catch(Exception ex)
    {
      ex.printStackTrace();
      transaction.rollback();
    }```


[quote="Fehlermeldung"]
javax.persistence.RollbackException: Error while commiting the transaction
	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
	at de.eaglesite.eaglemusikmanager.io.SQLConnection.saveAlbum(SQLConnection.java:99)
	at de.eaglesite.eaglemusikmanager.gui.AmazonAddDialog.addAlbums(AmazonAddDialog.java:404)
	at de.eaglesite.eaglemusikmanager.gui.AmazonAddDialog.access$1(AmazonAddDialog.java:395)
	at de.eaglesite.eaglemusikmanager.gui.AmazonAddDialog$1.actionPerformed(AmazonAddDialog.java:103)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.Component.processMouseEvent(Component.java:6038)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3260)
	at java.awt.Component.processEvent(Component.java:5803)
	at java.awt.Container.processEvent(Container.java:2058)
	at java.awt.Component.dispatchEventImpl(Component.java:4410)
	at java.awt.Container.dispatchEventImpl(Container.java:2116)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
	at java.awt.Container.dispatchEventImpl(Container.java:2102)
	at java.awt.Window.dispatchEventImpl(Window.java:2429)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:177)
	at java.awt.Dialog$1.run(Dialog.java:1039)
	at java.awt.Dialog$3.run(Dialog.java:1091)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.awt.Dialog.show(Dialog.java:1089)
	at java.awt.Component.show(Component.java:1419)
	at java.awt.Component.setVisible(Component.java:1372)
	at java.awt.Window.setVisible(Window.java:801)
	at java.awt.Dialog.setVisible(Dialog.java:979)
	at de.eaglesite.eaglemusikmanager.MainController.addAmazon(MainController.java:80)
	at de.eaglesite.eaglemusikmanager.gui.ToolBar$2.actionPerformed(ToolBar.java:121)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272)
	at java.awt.Component.processMouseEvent(Component.java:6038)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3260)
	at java.awt.Component.processEvent(Component.java:5803)
	at java.awt.Container.processEvent(Container.java:2058)
	at java.awt.Component.dispatchEventImpl(Component.java:4410)
	at java.awt.Container.dispatchEventImpl(Container.java:2116)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
	at java.awt.Container.dispatchEventImpl(Container.java:2102)
	at java.awt.Window.dispatchEventImpl(Window.java:2429)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
	at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:92)
	at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
	at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:222)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2229)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2665)
	at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:60)
	at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
	at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
	at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
	at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
	... 62 more
Caused by: java.sql.BatchUpdateException: Batch-Eintrag 0 insert into artists (name, artist_id) values (Crematory, 707) wurde abgebrochen.  Rufen Sie 'getNextException' auf, um die Ursache zu erfahren.
	at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2512)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1310)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:347)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2574)
	at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
	... 77 more
Exception occurred during event dispatching:
java.lang.IllegalStateException: Transaction not active
	at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.java:82)
	at de.eaglesite.eaglemusikmanager.io.SQLConnection.saveAlbum(SQLConnection.java:104)
	at de.eaglesite.eaglemusikmanager.gui.AmazonAddDialog.addAlbums(AmazonAddDialog.java:404)
	at de.eaglesite.eaglemusikmanager.gui.AmazonAddDialog.access$1(AmazonAddDialog.java:395)
	at de.eaglesite.eaglemusikmanager.gui.AmazonAddDialog$1.actionPerformed(AmazonAddDialog.java:103)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.Component.processMouseEvent(Component.java:6038)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3260)
	at java.awt.Component.processEvent(Component.java:5803)
	at java.awt.Container.processEvent(Container.java:2058)
	at java.awt.Component.dispatchEventImpl(Component.java:4410)
	at java.awt.Container.dispatchEventImpl(Container.java:2116)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
	at java.awt.Container.dispatchEventImpl(Container.java:2102)
	at java.awt.Window.dispatchEventImpl(Window.java:2429)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:177)
	at java.awt.Dialog$1.run(Dialog.java:1039)
	at java.awt.Dialog$3.run(Dialog.java:1091)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.awt.Dialog.show(Dialog.java:1089)
	at java.awt.Component.show(Component.java:1419)
	at java.awt.Component.setVisible(Component.java:1372)
	at java.awt.Window.setVisible(Window.java:801)
	at java.awt.Dialog.setVisible(Dialog.java:979)
	at de.eaglesite.eaglemusikmanager.MainController.addAmazon(MainController.java:80)
	at de.eaglesite.eaglemusikmanager.gui.ToolBar$2.actionPerformed(ToolBar.java:121)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272)
	at java.awt.Component.processMouseEvent(Component.java:6038)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3260)
	at java.awt.Component.processEvent(Component.java:5803)
	at java.awt.Container.processEvent(Container.java:2058)
	at java.awt.Component.dispatchEventImpl(Component.java:4410)
	at java.awt.Container.dispatchEventImpl(Container.java:2116)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
	at java.awt.Container.dispatchEventImpl(Container.java:2102)
	at java.awt.Window.dispatchEventImpl(Window.java:2429)
	at java.awt.Component.dispatchEvent(Component.java:4240)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
[/quote]

So damit es jetzt richtig komisch wird, ich hab gerade noch etwas mit Null rumprobiert.
Dabei kamen sehr komische Sachen raus, wenn das Album komplett neu ist, d.h. alle Attribute noch nie in der Datenbank waren. Kann ich es nicht speichern, dann kommt es zu der Exception da oben.
Enthält das Album aber einen Artist der schon aus der Datenbank stammt funktioniert es.

Hat jemand dafür eine Erklärung?

Am Besten postest du hier auch mal den Code von Album und Artist … und von deiner kompletten SQLConnection-Klasse. Und wenn du dann noch Zeit und Lust hast, evtl. noch ein Beispiel, wie das Album zusammen gebaut wird.

Hier hab ich die Sachen mal zusammen gepackt, in src-test liegt eine Testdatei wo ich ein Album zusammen packe. Das ist die einzige Einfügeoperation die mal funktioniert hat.

Genau so hab ich das auch immer gemacht. Eine andere Möglichkeit ist mir auch nicht bekannt.

Zu dem anderen Problem:
Hast du mal entitymanager.persist(album); probiert? Das hast du da ja auskommentiert stehen. Was kommt dabei heraus?

Für mich sieht es so aus, als ob es ne Diskrepanz zwischen den Objekten im Code und denen in der Datenbank gibt.

Vllt befinden sich die Objekte noch in einer anderen Session in einem persistenten Zustand?
Oder vllt sind die Objekte noch gar nicht persistiert?
Ne andere Möglichkeit wäre, dass eines der Alben nicht mehr in der DB vorhanden also gelöscht ist.
Ansonsten fällt mir noch ein, dass es öfters zu solchen Problemen kommt wenn man zwei verschiedene entitymanager Instanzen verwendet.

Das sind jetzt erstmal meine Vermutungen vllt helfen die ja weiter. Ich schau mir den Code später mal an.

Ob merge oder persist macht keinen Unterschied, läuft beides gleich gut/schlecht.
Die Datenbank lasse ich komplett von Hibernate erstellen.
Ich hab garkeine Sessions nur einen Entitymanager.

Jo das Album ist nicht in der Datenbank vorhanden, weil es neu ist :wink:

Mittlerweile hab ich aber eine Lösung gefunden, wobei das in meinen Augen mehr ein Workaround ist.
Alle Objekte die nicht in der Datenbank sind erstelle ich ja neu zusätzlich speichere ich sie in einer Hashtable ab damit ich, sollte das gleiche Objekt verlang werden, aber noch nicht in der Datenbank vorhanden ist, wieder das gleiche Objekt anbieten kann.
Das läuft auch nur trat der Fehler auch auf wenn ich nur ein Album einfügen wollte und diese Lösung dürfte eigentlich nur bei mehreren Alben helfen.

[QUOTE=EagleEye]Alle Objekte die nicht in der Datenbank sind erstelle ich ja neu zusätzlich speichere ich sie in einer Hashtable ab damit ich, sollte das gleiche Objekt verlang werden, aber noch nicht in der Datenbank vorhanden ist, wieder das gleiche Objekt anbieten kann.
Das läuft auch nur trat der Fehler auch auf wenn ich nur ein Album einfügen wollte und diese Lösung dürfte eigentlich nur bei mehreren Alben helfen.[/QUOTE]

Äh … hä?