-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: children not removed from db when removed from collection
PostPosted: Fri Oct 27, 2006 3:59 pm 
Beginner
Beginner

Joined: Fri Oct 27, 2006 3:35 pm
Posts: 21
Hi Folks,

I'll apologise now if this question has an obvious answer, but I've been stumped for days now even after trawling this forum and other online examples...

I've got a fairly typical 'user' / 'basket' / 'basket item' arrangement for an online shop. Each User has exactly 1 Basket, and BasketItems can be added to the Basket. The trouble is that when I come to remove BasketItems from the Basket, and persist the updated User object, the database doesn't reflect the changes made to the BasketItems collection.

I've set cascade="all" in both directions in the Basket and BasketItem mapping files (just in case ;) ), but this doesn't seem to have made a difference. I guess it must be a mapping file problem but I really can't figure out what.

I've written a simple junit testcase (below) to demonstrate the problem.

If anyone can offer some advice I'd be really grateful...

Cheers,
Richard.

Hibernate version:

3.1.3

Mapping documents:

==================================
User.hbm.xml
==================================

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

<hibernate-mapping>
<class name="uk.co.plugandplaydesign.dal.hibernate.User" table="user"
schema="public" lazy="false">
<id name="id" type="long" column="id" length="8">
<generator class="increment" />
</id>
<property name="emailAddress" type="string"
column="emailaddress" not-null="true" length="45" />
<property name="firstName" type="string" column="firstname"
length="25" />
<property name="lastName" type="string" column="lastname"
not-null="true" length="25" />
<property name="password" type="string" column="password"
not-null="true" length="15" />
<property name="staff" type="boolean" column="staff"
not-null="true" length="1" />
<property name="dateRegistered" type="date" column="dateregistered"
not-null="true" length="4" />
<property name="registrationKey" type="string" column="registrationkey"
not-null="true" length="16" />
<property name="title" type="string" column="title"
length="10" />
<property name="validated" type="boolean" column="validated"
not-null="true" length="1" />

<set name="contacts" cascade="all" inverse="true">
<key column="userid"/>
<one-to-many class="uk.co.plugandplaydesign.dal.hibernate.Contact"/>
</set>

<one-to-one name="basket" class="uk.co.plugandplaydesign.dal.hibernate.Basket" constrained="true" cascade="all"/>
</class>
</hibernate-mapping>


==================================
Basket.hbm.xml
==================================

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

<hibernate-mapping>
<class name="uk.co.plugandplaydesign.dal.hibernate.Basket"
table="basket" schema="public" lazy="false">
<id name="id" type="long" column="id" length="8">
<generator class="increment" />
</id>
<property name="userid" type="long" column="userid"
not-null="true" length="8" />

<one-to-one name="user" class="uk.co.plugandplaydesign.dal.hibernate.User" cascade="all"/>

<set name="basketItems" inverse="true" cascade="all">
<key column="basketid"/>
<one-to-many class="uk.co.plugandplaydesign.dal.hibernate.BasketItem"/>
</set>

</class>
</hibernate-mapping>

==================================
BasketItem.hbm.xml
==================================

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

<hibernate-mapping>
<class name="uk.co.plugandplaydesign.dal.hibernate.BasketItem"
table="basketitems" schema="public" lazy="false">
<id name="id" type="long" column="id" length="8">
<generator class="increment" />
</id>
<!-- <property name="basketid" type="long" column="basketid"
not-null="true" length="8" /> -->
<property name="productid" type="long" column="productid"
not-null="true" length="8" />
<property name="quantity" type="long" column="quantity"
not-null="true" length="8" />

<many-to-one name="basket" column="basketid" not-null="true" cascade="all"/>

</class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():

User, Basket and BasketItem are really just beans with getters and setters. The only exception is that when invoking User.setBasket(Basket b), b is also assigned a reference to the parent User. This is similarly true for BasketItems (which are each assigned a reference to the parent Basket). I'll post the code if it's needed.

public void testDelete() {
//ser up the user
User user = new User();
user.setEmailAddress("john.smith@somedomain.com");
user.setFirstName("John");
user.setLastName("Smith");
user.setPassword("password1");
user.setTitle("Mr");

//create a contact
Contact contact = new Contact();
contact.setAddressline1("10 Some Street");
contact.setCity("London");
contact.setCountry("UK");
contact.setPostcode("NW1");
contact.setTelephonenumber("012345 12345678");

user.addContact(contact);

//create an item for the basket
BasketItem basketItem = new BasketItem();
basketItem.setProductid(1);
basketItem.setQuantity(1);

//add the item to the basket
user.getBasket().addBasketItem(basketItem);

//persist the user and all its child objects
user = persistUser(user);

Query query = HibernateUtil.currentSession(hibernateConfig).createQuery("from User where emailaddress = 'john.smith@somedomain.com'");
List users = query.list();
//get an instance of the persisted user
user = (User)users.get(0);

Basket basket = user.getBasket();
//empty the basket
basket.emptyBasket();

//persist the user again
user = persistUser(user);

query = HibernateUtil.currentSession(hibernateConfig).createQuery("from User where emailaddress = 'john.smith@somedomain.com'");
users = query.list();
//get the persisted user again
user = (User)users.get(0);

//THIS BIT FAILS :-(
//assert that there are no items in the basket
assertTrue(user.getBasket().getBasketItems().isEmpty());
}

private User persistUser(User user) {
Transaction tx = null;
Session session = null;
User result = null;
try {
session = HibernateUtil.currentSession(this.hibernateConfig);
tx = session.beginTransaction();
result = (User)session.merge(user);
tx.commit();
session.flush();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
session.close();
}
return result;
}

Full stack trace of any exception that occurs:

No exception thrown

Name and version of the database you are using:

Postgres 8.1.4

The generated SQL (show_sql=true):

Hibernate: select max(id) from public.basket
Hibernate: select max(id) from public.basketitems
Hibernate: select max(id) from public.user
Hibernate: select max(id) from public.contact
Hibernate: insert into public.basket (userid, id) values (?, ?)
Hibernate: insert into public.basketitems (productid, quantity, basketid, id) values (?, ?, ?, ?)
Hibernate: insert into public.user (emailaddress, firstname, lastname, password, staff, dateregistered, registrationkey, title, validated, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into public.contact (addressline1, addressline2, city, postcode, telephonenumber, mobilenumber, county, country, userid, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: update public.basket set userid=? where id=?
Hibernate: select user0_.id as id2_, user0_.emailaddress as emailadd2_2_, user0_.firstname as firstname2_, user0_.lastname as lastname2_, user0_.password as password2_, user0_.staff as staff2_, user0_.dateregistered as dateregi7_2_, user0_.registrationkey as registra8_2_, user0_.title as title2_, user0_.validated as validated2_ from public.user user0_ where emailaddress='john.smith@somedomain.com'
Hibernate: select basket0_.id as id1_1_, basket0_.userid as userid1_1_, user1_.id as id2_0_, user1_.emailaddress as emailadd2_2_0_, user1_.firstname as firstname2_0_, user1_.lastname as lastname2_0_, user1_.password as password2_0_, user1_.staff as staff2_0_, user1_.dateregistered as dateregi7_2_0_, user1_.registrationkey as registra8_2_0_, user1_.title as title2_0_, user1_.validated as validated2_0_ from public.basket basket0_ left outer join public.user user1_ on basket0_.id=user1_.id where basket0_.id=?
Hibernate: select basket0_.id as id1_1_, basket0_.userid as userid1_1_, user1_.id as id2_0_, user1_.emailaddress as emailadd2_2_0_, user1_.firstname as firstname2_0_, user1_.lastname as lastname2_0_, user1_.password as password2_0_, user1_.staff as staff2_0_, user1_.dateregistered as dateregi7_2_0_, user1_.registrationkey as registra8_2_0_, user1_.title as title2_0_, user1_.validated as validated2_0_ from public.basket basket0_ left outer join public.user user1_ on basket0_.id=user1_.id where basket0_.id=?
Hibernate: select user0_.id as id2_, user0_.emailaddress as emailadd2_2_, user0_.firstname as firstname2_, user0_.lastname as lastname2_, user0_.password as password2_, user0_.staff as staff2_, user0_.dateregistered as dateregi7_2_, user0_.registrationkey as registra8_2_, user0_.title as title2_, user0_.validated as validated2_ from public.user user0_ where emailaddress='john.smith@somedomain.com'
Hibernate: select basket0_.id as id1_1_, basket0_.userid as userid1_1_, user1_.id as id2_0_, user1_.emailaddress as emailadd2_2_0_, user1_.firstname as firstname2_0_, user1_.lastname as lastname2_0_, user1_.password as password2_0_, user1_.staff as staff2_0_, user1_.dateregistered as dateregi7_2_0_, user1_.registrationkey as registra8_2_0_, user1_.title as title2_0_, user1_.validated as validated2_0_ from public.basket basket0_ left outer join public.user user1_ on basket0_.id=user1_.id where basket0_.id=?
Hibernate: select basket0_.id as id1_1_, basket0_.userid as userid1_1_, user1_.id as id2_0_, user1_.emailaddress as emailadd2_2_0_, user1_.firstname as firstname2_0_, user1_.lastname as lastname2_0_, user1_.password as password2_0_, user1_.staff as staff2_0_, user1_.dateregistered as dateregi7_2_0_, user1_.registrationkey as registra8_2_0_, user1_.title as title2_0_, user1_.validated as validated2_0_ from public.basket basket0_ left outer join public.user user1_ on basket0_.id=user1_.id where basket0_.id=?
Hibernate: select basketitem0_.basketid as basketid1_, basketitem0_.id as id1_, basketitem0_.id as id7_0_, basketitem0_.productid as productid7_0_, basketitem0_.quantity as quantity7_0_, basketitem0_.basketid as basketid7_0_ from public.basketitems basketitem0_ where basketitem0_.basketid=?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 27, 2006 4:23 pm 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
Without seeing your DAO code (and assuming that it is correct), try cascade="all,delete-orphan" on the set of basketItems.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 28, 2006 2:12 am 
Senior
Senior

Joined: Tue Aug 23, 2005 8:52 am
Posts: 181
Does your Basket.addBasketItem() set the reference on both sides of the relationship? You have a mapping like
Code:
<set name="basketItems" inverse="true" cascade="all">
<key column="basketid"/>
<one-to-many class="uk.co.plugandplaydesign.dal.hibernate.BasketItem"/>
</set>

which means the query will only take effect if the association is made from BaseketItem to Basket.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 28, 2006 6:23 am 
Beginner
Beginner

Joined: Fri Oct 27, 2006 3:35 pm
Posts: 21
Hi Ananasi,

Thanks for getting back to me. This worked a treat.

Ananasi wrote:
Without seeing your DAO code (and assuming that it is correct), try cascade="all,delete-orphan" on the set of basketItems.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.