Hi,
Ich habe folgendes Problem, wo mir selbst im Hibernateforum keiner helfen konnte. Aber vielleicht klappt es ja hier.
Ich habe zwei Tabellen. Customer für Kundeninformationen und CustomerContact für Kontaktinformationen für jeden Kunden. Diese Daten sind aus Performancegründen getrennt.
Die Customer-Tabelle verfügt über eine Spalte ID, welche autoinc ist (automatisch hochzählen) und somit auch ein Primärschlüssel. Die Tabelle CustomerContact enthält eine Spalte CustomerID, welche einfach nur ein Integer ist (und auch Primärschlüssel). Die Tabelle Customer hat also einen Fremdschlüssel von der Spalte ID auf die Spalte CustomerID der Tabelle CustomerContacts. (Hoffe ich konnte das soweit ordentlich erklären).
Das Problem ist nun folgendes. Wenn ich ein customer-Objekt in Java habe, also neu anlege, dann befülle ich alle Properties mit den entsprechenden Werten. Z.B. sage ich
So, ich setze also weder die ID von customer (weil die ja durch die AutoInc-Spalte automatisch zugewiesen wird, noch die CustomerID).
Beim Speichern des gesamten Objektes kommt folgende Exception.
Ich nehme an, dass folgendes passiert. Er will das Customer-Objekt in die Datenbank schreiben, vergibt die ID, z.B. 5, will dann die CustomerContact-Daten speichern, aber das Feld CustomerID ist ja null. Er erwartet aber 5. -> BOOM...
Nun ist die Frage, wie schaffe ich es, dass Hibernate automatisch diese 5, die es für die Spalte ID vergeben hat, automatisch an die Spalten weitergibt, die durch den Fremdschlüssel referenziert sind? Da gibt es bestimmt etwas, wie man die hbm.xml-Dateien konfigurieren kann.
Ich nutze ein Ant-Task, um mit HibernateTools diese Dateien anhand meiner MySQL-Datenbank zu generieren. Also müsste ich eigentlich die build.xml so anpassen, dass die hbm.xml-Dateien so generiert werden, dass das mit den Fremdschlüsseln klappt...
So, nun hab ich ja echt viel geschrieben. Hoffe das Problem ist klar geworden.
Hier mal noch meine build.xml, falls diese jemanden interessiert.
Ich habe folgendes Problem, wo mir selbst im Hibernateforum keiner helfen konnte. Aber vielleicht klappt es ja hier.
Ich habe zwei Tabellen. Customer für Kundeninformationen und CustomerContact für Kontaktinformationen für jeden Kunden. Diese Daten sind aus Performancegründen getrennt.
Die Customer-Tabelle verfügt über eine Spalte ID, welche autoinc ist (automatisch hochzählen) und somit auch ein Primärschlüssel. Die Tabelle CustomerContact enthält eine Spalte CustomerID, welche einfach nur ein Integer ist (und auch Primärschlüssel). Die Tabelle Customer hat also einen Fremdschlüssel von der Spalte ID auf die Spalte CustomerID der Tabelle CustomerContacts. (Hoffe ich konnte das soweit ordentlich erklären).
Das Problem ist nun folgendes. Wenn ich ein customer-Objekt in Java habe, also neu anlege, dann befülle ich alle Properties mit den entsprechenden Werten. Z.B. sage ich
Code:
Customer customer=new Customer();
customer.setName("Name");
customer.setFirstName("FirstName");
customer.setCustomercontact(new Customercontact());
customer.getCustomercontact.setMail("mail@server.com");
So, ich setze also weder die ID von customer (weil die ja durch die AutoInc-Spalte automatisch zugewiesen wird, noch die CustomerID).
Beim Speichern des gesamten Objektes kommt folgende Exception.
Code:
org.springframework.dao.DataIntegrityViolationException: could not insert: [de.nfranze.sf.model.Customer]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [de.nfranze.sf.model.Customer]
Caused by:
org.hibernate.exception.ConstraintViolationException: could not insert: [de.nfranze.sf.model.Customer]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:40)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2093)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2573)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:47)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:108)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:98)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
at org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:679)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:362)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:676)
at de.nfranze.sf.logic.dao.CustomerDAO.Save(CustomerDAO.java:38)
at de.nfranze.sf.logic.manager.CustomerManager.Create(CustomerManager.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:280)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:187)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:154)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:210)
at $Proxy8.Create(Unknown Source)
at de.nfranze.sf.controller.RegisterWizardController.processFinish(RegisterWizardController.java:160)
at org.springframework.web.servlet.mvc.AbstractWizardFormController.validatePagesAndFinish(AbstractWizardFormController.java:650)
at org.springframework.web.servlet.mvc.AbstractWizardFormController.processFormSubmission(AbstractWizardFormController.java:490)
at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:250)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:45)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:820)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:755)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:396)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:360)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:174)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:77)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:138)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Unknown Source)
Caused by: java.sql.SQLException: Cannot add or update a child row: a foreign key constraint fails (`sf/customer`, CONSTRAINT `FK_contact` FOREIGN KEY (`id`) REFERENCES `custcontact` (`customerid`))
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2975)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1600)
at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1129)
at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:681)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1368)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1283)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1268)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:73)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:33)
Ich nehme an, dass folgendes passiert. Er will das Customer-Objekt in die Datenbank schreiben, vergibt die ID, z.B. 5, will dann die CustomerContact-Daten speichern, aber das Feld CustomerID ist ja null. Er erwartet aber 5. -> BOOM...
Nun ist die Frage, wie schaffe ich es, dass Hibernate automatisch diese 5, die es für die Spalte ID vergeben hat, automatisch an die Spalten weitergibt, die durch den Fremdschlüssel referenziert sind? Da gibt es bestimmt etwas, wie man die hbm.xml-Dateien konfigurieren kann.
Ich nutze ein Ant-Task, um mit HibernateTools diese Dateien anhand meiner MySQL-Datenbank zu generieren. Also müsste ich eigentlich die build.xml so anpassen, dass die hbm.xml-Dateien so generiert werden, dass das mit den Fremdschlüsseln klappt...
So, nun hab ich ja echt viel geschrieben. Hoffe das Problem ist klar geworden.
Hier mal noch meine build.xml, falls diese jemanden interessiert.
Code:
<target name="Generate Database Objects" description="Middlegen hbm-Generation from MySQL">
<taskdef name="middlegen" classname="middlegen.MiddlegenTask">
<classpath refid="master-classpath"/>
</taskdef>
<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask">
<classpath refid="master-classpath"/>
</taskdef>
<middlegen
appname="Sf"
gui="false"
databaseurl="jdbc:mysql://fileserver/sf"
driver="com.mysql.jdbc.Driver"
username="root"
password="blabla"
schema="sf"
includeViews="false"
>
<hibernate
destination="${web.dir}/src"
package="de.nfranze.sf.model"
standardGeneratorScheme="native"
javaTypeMapper="middlegen.plugins.hibernate.HibernateJavaTypeMapper"/>
</middlegen>
<hibernatetool destdir="${web.dir}/src">
<configuration>
<fileset dir="${model.dir}">
<include name="**/*.hbm.xml"/>
</fileset>
</configuration>
<classpath refid="master-classpath"/>
<hbm2java jdk5="true"/>
</hibernatetool>
</target>