Hibernate + MySQL + Mapping Problem

Romsl

Erfahrenes Mitglied
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

Code:
<?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

Code:
<?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
 
Zuletzt bearbeitet:
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.
 
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?
 
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
 
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?
 
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.
Code:
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
 
Wie meinst du das mit dem Interceptor?

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