I have read a lot of articles and answers on similar questions, but i still can not understand.
Here my parent class:
@Entity
@Table(name = "users")
public class User implements Serializable, Annotation {
@Id
@GeneratedValue(generator = "system-uuid", strategy = GenerationType.IDENTITY)
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(name = "uuid", unique = true)
protected String uuid;
@Column(name = "username")
protected String username;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user", cascade = CascadeType.ALL)
private Set<UserItem> userItems;
}
Here we can see two sets - Items and Friends of User.
Example of UserItemId class:
@Entity
@Table(name = "user_item")
@AssociationOverrides({
@AssociationOverride(name = "pk.user",
joinColumns = @JoinColumn(name = "user_uuid")),
@AssociationOverride(name = "pk.ItemShop",
joinColumns = @JoinColumn(name = "item_shop_uuid")) })
public class UserItem implements Serializable {
@EmbeddedId
protected UserItemId pk = new UserItemId();
@Transient
public User getUser() {
return getPk().getUser();
}
public void setUser(User user) {
getPk().setUser(User);
}
@Transient
public ItemShop getItemShop() {
return getPk().getItemShop();
}
public void setItemShop(ItemShop ItemShop) {
getPk().setItemShop(ItemShop);
}
}
And now i'm trying to add new Item to user:
/*
'user' in this code i got from SecurityContext in controller
and I give it as parameter from controller to method (service layer) which can add new Item to user.
So user it is entity which already exists in database - it is logged user
*/
UserItem userItem = new UserItem();
userItem.setUser(user);
userItem.setItemShop(ItemShop);
user.getUserItems().add(userItem);
session.saveOrUpdate(user);
But i got an error:
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session
I understand that the main problem is in CascadeTypes - ALL it is not best variant for this, because hibernate can not do what i want - understand that User is a persistent object and just add to persistent new item and save it to database. So i want to ask you, what is the best practice to win in this situation, when i have Parent class (User) and children (Items) and i want to add new items and delete items from parent and save it to database. Indeed i found working method (using iterator), but i understand that on highload project it is the worst variant make for loop for such operations. I really want to find best practices for such situations.
QUESTION UPDATE: I've made mistake. When i call code which execute adding child to set (code above) - everything is good - child added in database and in entity, but when I'm trying to delete child:
Set<UserItem> userItems = user.getUserItems();
UserItem userItem = userDAO.findUserItem(user, itemShop);
userItems.remove(userItem);
session.saveOrUpdate(user);
session.flush();
Then i got exception:
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session
ONE MORE UPDATE:
After a lot of experiments i got working code of adding item:
UserItem userItem = new UserItem();
userItem.setUser(user);
userItem.setItemShop(ItemShop);
user.getUserItems().add(userItem);
session.saveOrUpdate(user);
It is a code of method in a Service layer which add item to user. And it is working. And i have half-working code to delete item from user:
Set<UserItem> userItems = user.getuserItems();
UserItem userItem = UserDAO.findUserItem(user, itemShop);
userItems.remove(userItem);
userDAO.merge(user);
It is not properly works code. We have a situation - user has 3 items. I delete one item - everything is fine. Later I'm trying to delete one more item and hibernate says me:
ObjectNotFoundException: No row with the given identifier exists
That means in cache still 3 items - that one i delete first - still in cache and hibernate try to add it into database - but it is deleted.
And i got one more mind idea, which can help us to answer this question. Object User - where i'm trying to delete child - it is logged user from SecurityContext - i got it from controller - controller has annotation where User got from Security. So, hibernate already has in cache logged user (User object). Any ideas?