Hi,
maybe this is a newbe-question, thus I would first like to show the application code.
I do have a Person-Class which is associated with a 1-1 mapping to a Adress class. I have a service method to create a Person-object.
Code:
void createPerson() {
springHibernateTemplate.save(person);
if (isInvalid(person))
throw Exception(); // and cause a rollback
}
Now my problem is this:
The first time createPerson() is called with an invalid person.
The transaction is rolled back.
The next time createPerson() is called with a valid person. It is the same object with different properties.
Now the transaction commits. But Hibernate only tries to create a new Person-object and not a corresponding Adress-object.
This is the debug output for the Insert:
Code:
DEBUG - AbstractFlushingEventListener.flushEverythingToExecutions(85) | Flushed: 1 insertions, 1 updates, 0 deletions to 2 objects
Hibernate: insert into PERSONEN (nachname, vorname, adresse, ID) values (?, ?, ?, ?)
And this is the error:
Code:
DEBUG - JDBCExceptionReporter.logExceptions(63) | could not insert: [de.akquinet.spring.kundenverwaltung.db.Kunde] [insert into PERSONEN (nachname, vorname, adresse, ID) values (?, ?, ?, ?)]
ERROR 23503: INSERT on table 'PERSONEN' caused a violation of foreign key constraint 'FK491016BE65BE6C18' for key (1081344). The statement has been rolled back.
To me it seems that in the first call Hibernate marked the adress object as saved. I could see in the debugger that the id is set. In the second call Hibernate tries to create the Person with a non existing Adress-ID.
Do I something wrong?
-- Torsten
Hibernate version: 3.1
Mapping documents:Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="de.akquinet.spring.kundenverwaltung.db.Adresse"
table="ADRESSEN">
<id name="id" column="ID" access="field">
<generator class="native"/>
</id>
<property name="stadt">
<column name="STADT" sql-type="VARCHAR(30)"/>
</property>
<component name="postleitzahl">
<property name="postleitzahl" access="field">
<column name="PLZ" sql-type="CHAR(5)"/>
</property>
</component>
<component name="strasseHausnummer">
<property name="strasse">
<column name="STRASSE" sql-type="VARCHAR(30)"/>
</property>
<property name="hausnummer">
<column name="HAUSNR" sql-type="VARCHAR(10)"/>
</property>
</component>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<joined-subclass name="de.akquinet.spring.kundenverwaltung.db.Kunde"
extends="de.akquinet.spring.kundenverwaltung.db.Person"
table="KUNDEN">
<key column="ID"/>
<property name="kundennummer"/>
</joined-subclass>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="de.akquinet.spring.kundenverwaltung.db.Person"
table="PERSONEN" abstract="true">
<id name="id" column="ID" access="field">
<generator class="native" />
</id>
<property name="nachname" />
<property name="vorname" />
<!-- 1-1 erfordert gleiche IDs, Adressen können aber auch von anderen Personen benutzt werden unique="true"-->
<many-to-one name="adresse" cascade="all"
access="field" lazy="false" not-null="true"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
public void createKunde(final Kunde neuerKundePrototyp)
throws NameSchonVorhandenException {
hibernateTemplate.save(neuerKundePrototyp);
if (isValid(neuerKundePrototyp)) {
throw new NameSchonVorhandenException();
}
}
Full stack trace of any exception that occurs:Code:
DEBUG - AbstractFlushingEventListener.prepareCollectionFlushes(153) | dirty checking collections
DEBUG - AbstractFlushingEventListener.flushEverythingToExecutions(85) | Flushed: 1 insertions, 1 updates, 0 deletions to 2 objects
Hibernate: insert into PERSONEN (nachname, vorname, adresse, ID) values (?, ?, ?, ?)
DEBUG - AbstractFlushingEventListener.flushEverythingToExecutions(91) | Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
DEBUG - Printer.toString(83) | listing entities:
DEBUG - Printer.toString(90) | de.akquinet.spring.kundenverwaltung.db.Adresse{postleitzahl=component[postleitzahl]{postleitzahl=13245}, stadt=ad, strasseHausnummer=component[strasse,hausnummer]{strasse=str, hausnummer=56}, id=1081344}
DEBUG - Printer.toString(90) | de.akquinet.spring.kundenverwaltung.db.Kunde{nachname=Meier, adresse=de.akquinet.spring.kundenverwaltung.db.Adresse#1081344, kundennummer=12345, vorname=Egon-Max, id=1048577}
DEBUG - AbstractBatcher.logOpenPreparedStatement(311) | about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
DEBUG - ConnectionManager.openConnection(415) | opening JDBC connection
DEBUG - Logger.debug(37) | StandardDataSource:getConnection Connection from DriverManager is returned
DEBUG - AbstractBatcher.log(346) | insert into PERSONEN (nachname, vorname, adresse, ID) values (?, ?, ?, ?)
DEBUG - AbstractBatcher.logClosePreparedStatement(319) | about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
DEBUG - JDBCExceptionReporter.logExceptions(63) | could not insert: [de.akquinet.spring.kundenverwaltung.db.Kunde] [insert into PERSONEN (nachname, vorname, adresse, ID) values (?, ?, ?, ?)]
ERROR 23503: INSERT on table 'PERSONEN' caused a violation of foreign key constraint 'FK491016BE65BE6C18' for key (1081344). The statement has been rolled back.
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
at org.apache.derby.impl.sql.execute.ForeignKeyRIChecker.doCheck(Unknown Source)
at org.apache.derby.impl.sql.execute.GenericRIChecker.doCheck(Unknown Source)
at org.apache.derby.impl.sql.execute.RISetChecker.doFKCheck(Unknown Source)
at org.apache.derby.impl.sql.execute.InsertResultSet.normalInsertCore(Unknown Source)
at org.apache.derby.impl.sql.execute.InsertResultSet.open(Unknown Source)
at org.apache.derby.impl.sql.GenericPreparedStatement.execute(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeUpdate(Unknown Source)
at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:23)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2062)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2427)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:51)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:985)
at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:130)
at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:48)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:707)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:523)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:510)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:310)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:209)
at $Proxy1.createKunde(Unknown Source)
at de.akquinet.spring.kundenverwaltung.gui.KundenAnlegenDialog.legeKundeAn(KundenAnlegenDialog.java:139)
at de.akquinet.spring.kundenverwaltung.gui.KundenAnlegenDialog.access$1(KundenAnlegenDialog.java:137)
at de.akquinet.spring.kundenverwaltung.gui.KundenAnlegenDialog$2.actionPerformed(KundenAnlegenDialog.java:130)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1849)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2169)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
at javax.swing.AbstractButton.doClick(AbstractButton.java:302)
at javax.swing.plaf.basic.BasicRootPaneUI$Actions.actionPerformed(BasicRootPaneUI.java:190)
at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1571)
at javax.swing.JComponent.processKeyBinding(JComponent.java:2763)
at javax.swing.KeyboardManager.fireBinding(KeyboardManager.java:255)
at javax.swing.KeyboardManager.fireKeyboardAction(KeyboardManager.java:204)
at javax.swing.JComponent.processKeyBindingsForAllComponents(JComponent.java:2840)
at javax.swing.JComponent.processKeyBindings(JComponent.java:2832)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2726)
at java.awt.Component.processEvent(Component.java:5265)
at java.awt.Container.processEvent(Container.java:1966)
at java.awt.Component.dispatchEventImpl(Component.java:3955)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1810)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:672)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:920)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:798)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:636)
at java.awt.Component.dispatchEventImpl(Component.java:3841)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Window.dispatchEventImpl(Window.java:1778)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:153)
at java.awt.Dialog$1.run(Dialog.java:517)
at java.awt.Dialog$2.run(Dialog.java:545)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Dialog.show(Dialog.java:543)
at java.awt.Component.show(Component.java:1300)
at java.awt.Component.setVisible(Component.java:1253)
at de.akquinet.spring.kundenverwaltung.gui.KundenlistePanel.legeNeuenKundenAn(KundenlistePanel.java:99)
at de.akquinet.spring.kundenverwaltung.gui.KundenlistePanel.access$0(KundenlistePanel.java:98)
at de.akquinet.spring.kundenverwaltung.gui.KundenlistePanel$1.actionPerformed(KundenlistePanel.java:91)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1849)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2169)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:5488)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3126)
at java.awt.Component.processEvent(Component.java:5253)
at java.awt.Container.processEvent(Container.java:1966)
at java.awt.Component.dispatchEventImpl(Component.java:3955)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3892)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
at java.awt.Container.dispatchEventImpl(Container.java:2010)
at java.awt.Window.dispatchEventImpl(Window.java:1778)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
WARN - JDBCExceptionReporter.logExceptions(71) | SQL Error: 30000, SQLState: 23503
Name and version of the database you are using:
Derby, 10.1.3.1
The generated SQL (show_sql=true):
Hibernate: insert into PERSONEN (nachname, vorname, adresse, ID) values (?, ?, ?, ?)
Debug level Hibernate log excerpt:
s.a.