Basicly I have 3 tables in a database: 'User', 'Item', 'ItemsPerUser'.
username (PK); password; email
name (PK)
username (PK) (and FK); item_name (PK) (and FK)
When I don't use cascading, I get an error: "Cannot add or update a child row: a foreign key constraint fails".
The mapping files are correct. I need some sort of cascading. It works when I add cascading in the set property of the many-to-many relationship to add non-existent data to User & Item, but it is overwriting data in ItemsPerUser. Whenever I save an object which contains one ore more items which was already entered in ItemsPerUser, it overwrites the row, even when the other part of the PK is not the same user. So basicly the previous user with that 'item' is overwritten by the new user with the same item. It should always add a new row in the table ItemsPerUser if it is a new user, even with one or more item(s) whom is already entered by another User object.
Assume I start with an empty database and I insert a new user Roger, who has two items: coffee and water. This is an example what happens (Hibernate handles this correct):
User ItemsPerUser Item
Roger Roger-coffee coffee
Roger-water water
Now when I insert a new user "Alfonzo" whom has the items coffee and soda, this happens:
User ItemsPerUser Item
Roger Alfonzo-coffee coffee
Alfonzo Roger-water water
Alfonzo-soda soda
//Mapping for databag 'User' - !! NOTE: I have deleted the cascade rule in the XML
<hibernate-mapping>
<class name="databag.User" table="User" catalog="androiddb">
<id name="username" type="string">
<column name="username" length="45" />
<generator class="assigned" />
</id>
<property name="password" type="string">
<column name="password" length="45" not-null="true" />
</property>
<property name="email" type="string">
<column name="email" length="45" not-null="true" unique="true" />
</property>
<set name="items" inverse="false" table="itemsperuser">
<key>
<column name="username" length="45" not-null="true" />
</key>
<many-to-many entity-name="databag.Items">
<column name="item_name" length="45" not-null="true"/>
</many-to-many>
</set>
</class>
</hibernate-mapping>
//Mapping for Item
<hibernate-mapping>
<class name="databag.Item" table="item" catalog="androiddb">
<id name="name" type="string">
<column name="name" length="45" />
<generator class="assigned" />
</id>
<set name="users" inverse="false" table="itemsperuser">
<key>
<column name="item_naam" length="45" not-null="true" />
</key>
<many-to-many entity-name="databag.User">
<column name="username" length="45" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
//Saving an object
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction trans = session.beginTransaction();
session.save((User)o);
trans.commit();
session.close();
Note: '(User)o' contains none, one or more items.
You can't set inverse="false" on both sides. Hibernate cannot persists both sets (users in Item and items in User) in the same table, unless one of them is called 'inverse', and can be savely ignored for writing. It will be filled up only when reading.
I'd set inverse="true" on the Item side.
Then you'd have to save items first, then adding them to a user, then saving the user.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With