Reputation: 23
I have following scenario: Table A and table B has Many-to-Many relationship. Class A is mapped to table A and Class B is Mapped to Table B and there is a Join table AB. Class A has Set of class B and Class B has Set of class A. I have Three different user interfaces to Create/Update A, B and AB. When I load A's information in A's UI I dont want to load list of B with that (performance reasons). So while saving A, I get only information related to A and Set is null. When I save this instance of A it deletes all existing mappings between A and B. Does hibernate allow such save? or do we always have to populate Set before saving A?
Database table A:
aid | data
---------
Database table B:
bid | data
---------
Database table AB:
aid | bid
----------
Class A{
private long aid;
private String data;
private Set<B> bSet;
}
Class B{
private long bid;
private String data;
private Set<A> aSet;
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name='test.A' table='A'>
<id name='aid' type='long' column='aid'>
</id>
<set name="bSet" table="AB"
inverse="false" fetch="select" cascade="save-update">
<key>
<column name="aid" not-null="true" />
</key>
<many-to-many entity-name="test.B">
<column name="bid" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name='test.B' table='B'>
<id name='bid' type='long' column='bid'>
</id>
<set name="aSet" table="AB"
inverse="false" fetch="select" cascade="save-update">
<key>
<column name="bid" not-null="true" />
</key>
<many-to-many entity-name="test.A">
<column name="aid" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
My table already has following data
Table A
aid | data
---------
1 | [json data_a1]
--------------------
2 | [json data_a2]
--------------------
Table B
bid | data
-----------
1 | [json data b1]
--------------------
2 | [json data b2]
Table AB
aid | bid
----------
1 | 1
----------
1 | 2
----------
2 | 1
----------
Now When I want to update A (say with Id 1), I have only A.data populated(UI send only data related to A. It does not know anything about A-B mapping), a.bSet is null or empty. And when I save this A, it deletes entries for mapping table.
String aJson = "{aid:1, data:['newJsonData']}";
A a = JsonParser.parse(aJson);
session.saveOrUpdate(a);
Table AB becomes
aid | bid
----------
2 | 1
----------
Is there any way to avoid this delete?
Upvotes: 2
Views: 1508
Reputation: 691625
Use merge()
rather than saveOrUpdate()
, and make sure you don't reset the set to a null set when merging:
String aJson = "{aid:1, data:['newJsonData']}";
A detachedA = JsonParser.parse(aJson);
A existingA = (A) session.get(A.class, detachedA.getId());
Set<B> bs = existingA.getBs(); // save the Bs to restore them afterwards
session.merge(detachedA);
existingA.setBs(bs); // restore the Bs
Upvotes: 1