# Hibernate + MySQL + Mapping Problem



## Romsl (23. April 2005)

Hi,

ich habe eine MySQL Datenbank und verwende Hibernate um Daten persistent zu speichern, ändern, löschen und suchen.

Mein Ziel wäre es eine Person mit einer Adresse zu haben. Eine Adresse kann aber zu mehreren Personen gehören.

Ich kann wunderbar einfügen, ändern und suchen. Aber mit dem Löschen habe ich Probleme. Wenn ich eine Person lösche wird die Adresse mitgelöscht und somit auch alle anderen Personen. Nun möchte ich aber nur die Person löschen die Adresse behalten solange dann noch eine Person mit der Adresse besteht. Falls dies nicht zutrifft möchte ich auch die Adresse aus der DB löschen.

Hier meine Mappings.

Address.hbm.xml


```
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="ebooking.module.base.bean.address.Address" table="BASE_ADDRESS">
        <id name="id" type="long">
            <column name="ID" not-null="true"/>
            <generator class="increment"/>
        </id>

        <property name="street" type="string">
            <column name="STREET" length="100" not-null="false"/>
        </property>

        <property name="zipCode" type="string">
            <column name="ZIPCODE" length="25" not-null="false"/>
        </property>

        <property name="city" type="string">
            <column name="CITY" length="100" not-null="false"/>
        </property>

        <property name="countyId" type="long">
            <column name="COUNTY_ID" length="100" not-null="false"/>
        </property>

        <property name="countryId" type="long">
            <column name="COUNTRY_ID" length="100" not-null="false"/>
        </property>

        <property name="stateId" type="long">
            <column name="STATE_ID" length="100" not-null="false"/>
        </property>

        <property name="postalName" type="string">
            <column name="POSTAL_NAME" length="100" not-null="false"/>
        </property>

        <property name="department" type="string">
            <column name="DEPARTMENT" length="150" not-null="false"/>
        </property>

        <property name="phone1" type="string">
            <column name="PHONE1" length="100" not-null="false"/>
        </property>

        <property name="phone2" type="string">
            <column name="PHONE2" length="100" not-null="false"/>
        </property>

        <property name="telefax" type="string">
            <column name="FAX" length="100" not-null="false"/>
        </property>

        <property name="mobilePhone" type="string">
            <column name="MOBILE_PHONE" length="100" not-null="false"/>
        </property>

        <property name="email" type="string">
            <column name="EMAIL" length="100" not-null="false"/>
        </property>

        <property name="www" type="string">
            <column name="WWW" length="150" not-null="false"/>
        </property>

        <set name="persons" table="BASE_PERSON" inverse="true" cascade="all" lazy="true">
            <key column="ADDRESS_ID"/>
            <one-to-many class="ebooking.module.base.bean.person.Person"/>
        </set>

        <!--
        <set name="persons" table="BASE_PERSON_ADDRESS" cascade="all">
            <key column="ADDRESS_ID" not-null="true"/>
            <many-to-many class="ebooking.module.base.bean.person.Person">
                <column name="PERSON_ID"/>
            </many-to-many>
        </set>
        -->
    </class>

    <class name="ebooking.module.base.bean.address.Country" table="BASE_ADDRESS_COUNTRY">
        <id name="id" type="long">
            <column name="ID" not-null="true"/>
            <generator class="increment"/>
        </id>

        <property name="name" type="string">
            <column name="NAME" length="100" not-null="true"/>
        </property>

        <!--
        <set name="counties" table="BASE_ADDRESS_COUNTY" cascade="all">
            <key column="ADDRESS_COUNTRY_ID"/>
            <one-to-many class="ebooking.module.base.bean.address.County"/>
        </set>
        -->
    </class>

    <class name="ebooking.module.base.bean.address.County" table="BASE_ADDRESS_COUNTY">
        <id name="id" type="long">
            <column name="ID" not-null="true"/>
            <generator class="increment"/>
        </id>

        <property name="name" type="string">
            <column name="NAME" length="100" not-null="true"/>
        </property>
    </class>

</hibernate-mapping>
```

und Person.hbm.xml


```
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="ebooking.module.base.bean.person.Person" table="BASE_PERSON">
        <id name="id" type="long">
            <column name="ID" not-null="true"/>
            <generator class="increment"/>
        </id>

        <property name="titleId" type="long">
            <column name="TITLE" not-null="false"/>
        </property>

        <property name="academicTitleId" type="long">
            <column name="ACADEMIC_TITLE" not-null="false"/>
        </property>

        <property name="firstname" type="string">
            <column name="FIRSTNAME" not-null="false"/>
        </property>

        <property name="lastname" type="string">
            <column name="LASTNAME" not-null="false"/>
        </property>

        <many-to-one name="address" column="ADDRESS_ID" class="ebooking.module.base.bean.address.Address" cascade="all"/> 

        <!--
        <set name="addresses" table="BASE_PERSON_ADDRESS" cascade="all">
            <key column="PERSON_ID" not-null="true"/>
            <many-to-many class="ebooking.module.base.bean.address.Address">
                <column name="ADDRESS_ID"/>
            </many-to-many>
        </set>
        -->
    </class>

    <class name="ebooking.module.base.bean.person.Title" table="BASE_PERSON_TITLE">
        <id name="id" type="long">
            <column name="ID" not-null="true"/>
            <generator class="increment"/>
        </id>

        <property name="title" type="string">
            <column name="TITLE" length="50" not-null="true"/>
        </property>
    </class>

    <class name="ebooking.module.base.bean.person.AcademicTitle" table="BASE_PERSON_ACADEMIC_TITLE">
        <id name="id" type="long">
            <column name="ID" not-null="true"/>
            <generator class="increment"/>
        </id>

        <property name="academicTitle" type="string">
            <column name="ACADEMIC_TITLE" length="100" not-null="true"/>
        </property>
    </class>
</hibernate-mapping>
```

Ich versuch das nun schon seit 2 Tagen, durchforste das gesamte Web. Aber ich finde leide keine passende Lösung für mein Problem.

Gruß

Romsl


----------



## cham (24. April 2005)

Als aller erstes musst Du in der relation definition das all gegen insert, update austauschen.

Du musst aber dann selbst dafür sorgen, dass die Adressen im Falle des Falles gelöscht werden.


----------



## Romsl (24. April 2005)

Leider gibt es kein insert und update.

Es muss doch möglich sein, dass hibernate das ganze übernimmt. Wozu sonst gibt es all-delete-orphan oder delete orphan?


----------



## cham (24. April 2005)

okay, mein fehler:

so musses heissen: cascade="save-update"


----------



## Romsl (24. April 2005)

Bist du Dir ganz sicher, dass ich in meiner Logik selbst feststellen muss ob noch eine Person zu dieser Adresse besteht und wenn nicht selbst löschen?

Gruß und Danke

Romsl


----------



## cham (24. April 2005)

ich müsste nochmal nachlesen. aber etwas anderes ist mir nicht bekannt.


----------



## Thomas Darimont (24. April 2005)

Hallo!

Ist für solche Problemstellungen nicht die Option "delete-orphan" da?

Gruß Tom


----------



## Romsl (24. April 2005)

Das hab ich eigenlich auch gedacht.

Aber leider funktionierts bei mir nicht. Hat jemand irgend ein Beispiel (1:n Beziehung)?
Oder kann mir jemand sagen woran mein Fehler liegt. An der Datenbank sollts ja nicht liegen, oder?


----------



## Thomas Darimont (24. April 2005)

Hallo!

Leider funktioniert delete-orphan nicht mit many-to-one Beziehungen (hier: Mehrere Personen haben die gleiche Addresse). Wenn du cascade auf save-update stellst umgehst du das Problem nur löst es aber nicht. Da gibt es sicherlich noch einen anderen Weg... ein Interceptor vielleicht?

Anonsten könntest du mit einer solchen Abfrage feststellen, ob die Person die du löschen willst die einzige ist die auf die damit Assoziierte Addresse referenziert.

```
Person personToDelete = (Person) session.load(Person.class, Long
				.valueOf(393218L));

		List list = session.find(
				"from Person p where p.id <> ? and p.address.id = ?",
				new Object[] { personToDelete.getId(),
						personToDelete.getAddress().getId() }, new Type[] {
						Hibernate.LONG, Hibernate.LONG });
		System.out.println("Address is orphaned: " + (list.size() < 0));
```

Gruß Tom


----------



## Romsl (24. April 2005)

Wie meinst du das mit dem Interceptor?

Würde es eigentlich mit many-to-many funktionieren? Wenn ja, wie?


----------



## Romsl (24. April 2005)

Ich hänge leider immernoch an diesem Problem.

@Thomas: Bei deiner Lösung tritt eine re-saved... error message auf.


----------



## Romsl (26. April 2005)

Leider bin ich immernoch keinen Schritt weitergekommen. Und finde auch keine (weder bei hibernate.org oder sonstigen Foren) Hilfe für mein Problem.

Wäre für jede noch so kleine Hilfe dankbar.

Gruß

Romsl


----------



## cham (27. April 2005)

Könntest Du wenigstens mal den Fehler posten? Original bitte.


----------



## Romsl (27. April 2005)

```
org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException: deleted object would be re-saved by cascade (remove deleted object from associations): [ebooking.module.base.bean.person.Person#8]; nested exception is org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [ebooking.module.base.bean.person.Person#8]
org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [ebooking.module.base.bean.person.Person#8]
	at org.hibernate.impl.SessionImpl.forceFlush(SessionImpl.java:690)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:166)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:96)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:69)
	at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:432)
	at org.hibernate.engine.Cascades$5.cascade(Cascades.java:153)
	at org.hibernate.engine.Cascades.cascade(Cascades.java:721)
	at org.hibernate.engine.Cascades.cascadeCollection(Cascades.java:860)
	at org.hibernate.engine.Cascades.cascade(Cascades.java:739)
	at org.hibernate.engine.Cascades.cascade(Cascades.java:817)
	at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:121)
	at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:112)
	at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:59)
	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:678)
	at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:309)
	at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
	at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:470)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:401)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(TransactionAspectSupport.java:256)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:67)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
	at $Proxy1.deleteCustomerByPersonId(Unknown Source)
	at ebooking.module.base.controller.CustomerController.deleteCustomerForm(CustomerController.java:84)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at org.springframework.web.servlet.mvc.multiaction.MultiActionController.invokeNamedMethod(MultiActionController.java:351)
	at org.springframework.web.servlet.mvc.multiaction.MultiActionController.handleRequestInternal(MultiActionController.java:305)
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:128)
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:44)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:675)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:623)
	at org.springframework.web.servlet.FrameworkServlet.serviceWrapper(FrameworkServlet.java:384)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:344)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
	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.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
	at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
	at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
	at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
	at java.lang.Thread.run(Thread.java:534)
```


----------



## Buteur (10. Juli 2005)

Hallo,
ich habe das selbe Problem. Das wäre nett, wenn Du mir sagen, falls Du schon das Problem gelöst hast, wie?
Gruss,


----------



## Romsl (10. Juli 2005)

Ich hab das cascading auf save-update gesetzt und prüfe jetzt jedesmal nach ob es zu einer Adresse noch eine Person gibt. Wenn nicht lösche ich die Adresse auch, falls doch lasse ich das mit dem Löschen.

Es geht bestimmt auch besser, aber wie kann ich Dir leider nicht sagen. Falls du was besseres hast, lass es mich bitte wissen.


----------



## ErikVDH (5. März 2008)

Falls es noch jemanden interessiert ...

Es funktioniert auch mit "all-delete-orphan". Man muss sich nur das Objekt (in diesem Fall die Person) holen und die Collection neu initalisieren (sprich eine neue Instanz für die Collection erzeugen). 

Hat zumindest bei mir geklappt.

Habe das hier dazu gefunden:

http://www.mail-archive.com/users@appfuse.dev.java.net/msg09839.html


----------

