I was really hoping someone had any clues, I have done a minimal example that will replicate the problem I have.
First of all I am using Hibernate 3.0-alpha.
The example has a category and an item class mapped as:
Code:
<hibernate-mapping>
<class name="Test.Category" table="Category">
<id name="id" type="integer" unsaved-value="0" >
<generator class="identity"/>
</id>
<property name="name" not-null="true"/>
<set name="Items" cascade="all" lazy="false">
<key column="catId"/>
<one-to-many class="Test.Item"/>
</set>
</class>
</hibernate-mapping>
Code:
<hibernate-mapping>
<class name="Test.Item" table="Item">
<id name="id" type="integer" unsaved-value="0" >
<generator class="identity"/>
</id>
<property name="name" not-null="true"/>
<many-to-one name="cat" class="Test.Category" column="catId" not-null="true" cascade="none"/>
</class>
</hibernate-mapping>
The following classes implement Category and Item:
Code:
public class Category implements Serializable {
int id;
String name;
Set items;
public Category() {
this.id = 0;
this.name = "new";
items = new HashSet();
}
public Category(int id,String name) {
this.id = id;
this.name = name;
items = new HashSet();
}
/Removed simple getters/setters
public static Category newInstance(Category o) {
Category c = new Category(o.getId(),o.getName());
for (Iterator it = o.getItems().iterator(); it.hasNext();) {
Item item = (Item) it.next();
c.items.add(Item.newInstance(c,item));
}
return c;
}
}
Code:
public class Item {
private int id;
private String name;
Category cat;
public Item() {
this.id = 0;
this.name = "new";
this.cat = null;
}
public Item(int id, String name, Category cat) {
this.id = id;
this.name = name;
this.cat = cat;
}
/Removed simple getters/setters
public static Item newInstance(Category c,Item o) {
Item item = new Item(o.getId(),o.getName(),o.getCat());
return item;
}
}
If I execute the following:
Session 1: Get a Category object
Close session 1
Copy object graph (to simulate the behavior I described above with my webservice scenario)
Session 2: call saveOrUpdate on the copy
Code:
Code:
Session session = PiM.Server.PiMServer.getSessions().openSession();
Transaction tx=null;
try {
tx = session.beginTransaction();
Category cat = (Category) session.get(Category.class,new Integer(1));
tx.commit();
session.close();
Category clone = Category.newInstance(cat);
tx=null;
session = PiM.Server.PiMServer.getSessions().openSession();
tx = session.beginTransaction();
session.saveOrUpdate(clone);
tx.commit();
} catch (HibernateException he){
if (tx!=null)
tx.rollback();
throw he;
} finally {
session.close();
}
I get the following log:
Code:
Hibernate: select category0_.id as id0_, category0_.name as name4_0_ from Category category0_ where category0_.id=?
Hibernate: select items0_.catId as catId__, items0_.id as id__, items0_.id as id0_, items0_.name as name5_0_, items0_.catId as catId5_0_ from Item items0_ where items0_.catId=?
Hibernate: update Category set name=? where id=?
Hibernate: update Item set name=?, catId=? where id=?
Hibernate: update Item set name=?, catId=? where id=?
Hibernate: update Item set name=?, catId=? where id=?
Hibernate: update Item set name=?, catId=? where id=?
Hibernate: update Item set name=?, catId=? where id=?
Hibernate: update Item set catId=null where catId=?
2004-sep-23 12:29:02 org.hibernate.util.JDBCExceptionReporter logExceptions
VARNING: SQL Error: -407, SQLState: 23502
2004-sep-23 12:29:02 org.hibernate.util.JDBCExceptionReporter logExceptions
ALLVARLIG: [IBM][CLI Driver][DB2/NT] SQL0407N Assignment of a NULL value to a NOT NULL column "TBSPACEID=2, TABLEID=5, COLNO=2" is not allowed. SQLSTATE=23502
Any one have any clue why Hibernate will do the update:
update Item set catId=null where catId=?
Which is clearly wrong.
Cheers Okku