[hibernate-issues] [Hibernate-JIRA] Resolved: (HHH-2679) One to Many Unidirectional Association using Join Tables and <list> causes duplicate key constraint violation when an entry is deleted from the list.
Diego Pires Plentz (JIRA)
noreply at atlassian.com
Sat Oct 13 21:24:38 EDT 2007
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-2679?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Diego Pires Plentz resolved HHH-2679.
-------------------------------------
Assignee: Diego Pires Plentz
Resolution: Duplicate
> One to Many Unidirectional Association using Join Tables and <list> causes duplicate key constraint violation when an entry is deleted from the list.
> -----------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: HHH-2679
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2679
> Project: Hibernate3
> Issue Type: Bug
> Components: core
> Affects Versions: 3.2.2
> Environment: Java 1.5, Hibernate 3.2, MySQL 5. Might also effect NHibernate similarly.
> Reporter: Darth
> Assignee: Diego Pires Plentz
> Priority: Critical
> Original Estimate: 2 weeks
> Remaining Estimate: 2 weeks
>
> Consider this unidirectional one-to-many relation done using join tables.
> Person --> Address (*).
> The hibernate mapping is pretty much the same as
> http://www.hibernate.org/hib_docs/v3/reference/en/html/associations.html#assoc-unidirectional-join-12m
> Though I am using <list> rather than a <set>
> Following is the DDL (presented roughly) created by the hbm2ddl tool.
> Table PersonAddress
> Person_id varcahr not null
> Address_id varchar not null unique
> Person_list_index integer not null
> primary key (Person_id, Person_list_index)
> I create a person1 - person_id=1.
> I create add1, add2, add3 - address_id=2,3,4 respectively.
> then I add all 3 addresses to the list in person1.
> persist it to database.
> all good.
> At this point in the database --
> person_id---person_list_index---address_id
> 1--0--2
> 1--1--3
> 1--2--4
> I get person1 back.
> I remove add1.
> save person1 back.
> CONSTRIANT VIOLATION HERE DUE TO DUPLICATE KEY.
> looking at what hibernate does ...
> So after 1st save and before remove this is whats in the database -
> person_id---person_list_index---address_id
> 1--0--2
> 1--1--3
> 1--2--4
> basically shows the one to many there.
> I want to remove the record no. 1--0--2. That is the 1st one.
> So with the 1st row gone, hibernate needs to shift other records up so that the new list index is assingned.
> expected output----
> 1--0--3
> 1--1--4
> This is how hibernate proceeds
> Step1: save info and delete on 1--2--4, to get rid of that last record.
> Step2: update 1--0--2 to 1--0--3
> BANG...CONSTRAINT VIOLATION DUE TO DUPLICATE KEY.
> Why? because "3" in that address_id column is already there and that column is "unique" according to DDL.
> Step3: update 1--0--3 to info saved from step1, that is to 1--1--4.
> But cant persist this since step 2 fails.
> Basically the algorithm of copy the value up when a delete is performed is not doing the copy correctly.
> Way to get around this is to remove the "unique" constrint, but then that makes the relation a many to many.
> -----------------------------------------------------------------------------
> CREATE TABLE `PERSON`
> (
> `PRESON_ID` varchar(255) NOT NULL, PRIMARY KEY (PRESON_ID)
> )
> CREATE TABLE `ADDRESS`
> (
> `ADDRESS_ID` varchar(255) NOT NULL, PRIMARY KEY (ADDRESS_ID)
> )
> CREATE TABLE `PERSONADDRESS`
> (
> `PERSON_ID` varchar(255) NOT NULL
> , `PERSON_IDX` integer NOT NULL
> , `ADDRESS_ID` varchar(255) NOT NULL UNIQUE, PRIMARY KEY (PERSON_ID, PERSON_IDX)
> )
> ALTER TABLE `PERSONADDRESS`
> ADD INDEX `PERSONADDRESS_FK_PERSON` (`PERSON_ID`),
> ADD CONSTRAINT `PERSONADDRESS_FK_PERSON`
> FOREIGN KEY (`PERSON_ID`)
> REFERENCES PERSON(`PERSON_ID`)
> ALTER TABLE `PERSONADDRESS`
> ADD INDEX `PERSONADDRESS_FK_ADDRESS` (`ADDRESS_ID`),
> ADD CONSTRAINT `PERSONADDRESS_FK_ADDRESS`
> FOREIGN KEY (`ADDRESS_ID`)
> REFERENCES ADDRESS(`ADDRESS_ID`)
> Person.hbm.xml
> -------------------------
> <list name="AddressList" lazy="false" table="PersonAddress">
> <key column="PERSON_ID" />
> <index column="PERSON_IDX" />
> <many-to-many column="ADDRESS_ID" unique="true" class="Address" />
> </list>
> Address.hbm.xml
> --------------------------
> No information about Person, since this is a unidirectional association.
> Target doesnt know about the source.
> Test psuedocode
> -------------------------
> //start transaction
> Person person = new Person();
> Address add1 = new Address();
> Address add2 = new Address();
> Address add3 = new Address();
> person.add(add1);
> person.add(add2);
> person.add(add3);
> // persist to database
> person.save
> // end transaction
> // start transaction
> // get back that person from database
> person.remove(add1);
> // persist to database
> person.save <<<<<<<<<<<<<<< FAILS, duplicate key constraint violation
> // end transaction
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the hibernate-issues
mailing list