2010-11-30 7 views
0

Ich habe einen einfachen Fall zum Testen erstellt und ich bekomme nicht das erwartete Verhalten. Ich bin interessiert, warum Hibernate wählt, die Elterntabelle (Land) zu aktualisieren, obwohl ich update = "false" -Attribut für die Viele-zu-eins-Beziehung (in der Address.hbm.xml) zur Verfügung stelle?Warum erlaubt Hibernate die Aktualisierung einer übergeordneten Tabelle, obwohl update = "false" für die Viele-zu-Eins-Beziehung bereitgestellt wird?

Die DDLs:

CREATE TABLE Country (
    `id` smallint NOT NULL auto_increment, 
    `name` varchar(100) NOT NULL, 
    PRIMARY KEY (`id`) 
) TYPE=InnoDB AUTO_INCREMENT=0; 
CREATE TABLE Address (
    `id` bigint NOT NULL auto_increment, 
    `firstName` varchar(100) NOT NULL, 
    `lastName` varchar(100) NOT NULL, 
    `countryId` smallint NOT NULL, 
    PRIMARY KEY (`id`), 
    FOREIGN KEY (countryId) 
    REFERENCES Country(id) 
    ON UPDATE CASCADE ON DELETE RESTRICT 
) TYPE=InnoDB AUTO_INCREMENT=0; 

Die Hibernate xmls:

<class name="Country" table="Country" lazy="false"> 
    <id name="id" column="id" type="integer"> 
     <generator class="native" /> 
    </id> 
    <property name="name" type="string" not-null="true" length="100"/> 
</class> 
<class name="Address" table="Address" > 
    <id name="id" column="id" type="long" unsaved-value="-1"> 
     <generator class="native" /> 
    </id> 
    <property name="addressFirstName" column="firstName" type="string" not-null="true" length="100"/> 
    <property name="addressLastName" column="lastName" type="string" not-null="true" length="100"/> 
    <!-- Country is parent table, Address is child table (holds the FK countryId). 
     From MySQL: 
     CASCADE: Update the row from the parent table and automatically update the matching rows in the child table. 
     RESTRICT: Rejects the delete operation for the parent table. 
     From hibernate: 
     1. cascade (optional): specifies which operations should be cascaded from the parent object to the associated object. 
     2. update, insert (optional - defaults to true): specifies that the mapped columns should be included in SQL UPDATE 
     and/or INSERT statements. Setting both to false allows a pure "derived" association whose value is initialized 
     from another property that maps to the same column(s), or by a trigger or other application. 
    --> 
    <many-to-one name="country" class="Country" column="countryId" 
     not-null="true" cascade="persist,merge,save-update" update="false" /> 
    <many-to-one name="state" class="State" column="stateId" 
     cascade="persist,merge,save-update" update="false" /> 
</class> 

My Country Tabelle hat eine Zeile (id = 1):

INSERT INTO Country (name) VALUES ("United States"); 

Wenn ich folgendes:

Country country = getCountryFrom("US"); 
Address address = new Address(); 
address.setAddressFirstName("Deksa"); 
address.setAddressLastName("Jakim"); 
country.setName("Slovenia"); 
address.setCountry(country); 
address.setId(-1); 
saveAddress(address); 
session.saveOrUpdate(address); 

Ich erwarte, dass ich eine neue Zeile in die Adresstabelle eingefügt habe, aber ich bekomme auch eine Aktualisierung in der Tabelle Land - die einzige Zeile, der Name des Landes wird Slowenien, anstatt in den Vereinigten Staaten zu bleiben (erwartetes Verhalten < = update = "false"):

Hibernate: select country0_.id as id6_, country0_.name as name6_ from Country country0_ where country0_.stringId='US' 
Hibernate: insert into Address (firstName, lastName, countryId) values (?, ?, ?) 
Hibernate: update Country set name=? where id=? 

warum überwintert nicht die übergeordnete Tabelle aktualisieren, wenn angewiesen, nicht zu?

Mit freundlichen Grüßen,
Despot

Edit: Kurz nach diesem Beitrag schreibt ich erkennen, dass ich mit dem Hibernate Kaskade der DB Kaskade bin verwirrend und dadurch gelöst, dass all meine Probleme.
Die Sache ist folgende: Hibernate klar sagt:

Update einfügen (optional - standardmäßig true): gibt an, dass die abgebildeten Spalten in SQL UPDATE und/oder INSERT-Anweisungen enthalten sein. Einstellung auf "false" erlaubt eine reine "abgeleitete" Assoziation, deren Wert aus einer anderen Eigenschaft initialisiert wird, die auf die gleiche (n) Spalte (n) abbildet, oder durch einen Trigger oder eine andere Anwendung.

. Das heißt, wenn update = "false" auf der Land-Eigenschaft (auf der countryId) verwendet wird, sage ich zu Ruhezustand. UPDATE Adresse SET firstName = "x", lastName = "y", countryId = 123 wo Bedingung; Führen Sie nur ein Update ohne die Länder-ID durch.
Dann sah ich, dass die ON UPDATE CASCADE der DB bezieht sich auf die Elterntabelle (Land) - wenn das Land aktualisiert wurde, dann aktualisieren Sie die Kind-Tabelle (die countryId Spalte in Adresstabelle). Im Gegensatz zu dem, was ich für das Update von hibernate hielt, erkannte ich, dass ich mit cascade = "save-update" zu hibebnate sage, welche Werte auch immer Sie für das Country-Objekt im Adressobjekt in seiner eigenen Country-Tabelle haben. Also war die Lösung Kaskade = "persist, merge" ohne den save-update Teil!

Antwort

1

Einstellung update = "false" auf country Eigenschaft ermöglicht es Ihnen nicht um die entsprechende countryId Feld zu aktualisieren, das heißt eine andere Country für bestimmte Address zu wählen.

Wenn Sie chaning des Namens Country bestehender deaktivieren möchten, müssen Sie update = "false" auf die entsprechende Eigenschaft angeben:

<class name="Country" table="Country" lazy="false"> 
    ... 
    <property name="name" type="string" not-null="true" length="100" update = "false" /> 
</class> 
+0

I Aktualisierung des Landes (Child-Objekt) verbieten wollte, kein Kind nicht zulassen Eigenschaft des Objekts. In meinem Fall, wenn ich eine andere Klasse habe (zum Beispiel Kontinent), die das Land als Kind/Mitglied-Objekt hat, und wenn ich dieser Elternklasse (Kontinent) erlauben wollte, das Land zu aktualisieren, wäre das nicht möglich. Mit anderen Worten, ich denke, auf diese Weise werden Sie die Aktualisierung der Namenseigenschaft des Landes von überall deaktivieren, was nicht das ist, was ich möchte. Wie auch immer, danke für die Antwort! – despot