Есть класс User:
@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;
}
У него есть дети Set.
Класс UserItem:
@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);
}
}
У сета useritem стоит тип каскадных операций "ALL" - то есть все изменения с полями класса User также отразятся на его детях. HIbernate пройдется по ним и применит все изменения.
Исполняем код добавления детеныша:
UserItem userItem = new UserItem();
userItem.setUser(user);
userItem.setItemShop(ItemShop);
user.getUserItems().add(userItem);
session.saveOrUpdate(user);
session.flush();
Детеныш добавится и в объект user и в базу данных. Если выполнить merge - детеныш добавится только в сущность - что есть правильно.
Удаляем детеныша:
Set<UserItem> userItems = user.getUserItems();
UserItem userItem = userDAO.findUserItem(user, itemShop);
userItems.remove(userItem);
session.saveOrUpdate(user);
session.flush();
Получаем исключение:
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.test.User#2d0767d8-effb-41f2-8910-5729a460527d]
Что я делаю не так? Откуда exception?
UPDATED:
Получил следующий рабочий код на удаление:
User user = UserDetails.getUser();
Set<UserItem> userItems = user.getUserItems();
UserItem userItem = UserDAO.findUserItem(user, itemShop);
UserItems.remove(UserItem);
session.merge(user);
session.flush();
session.clear();
Да только не чисто работает код, а суть в следующем, у юзера есть 3 Item, удаляю первый - мержу - все окей, удаляю второй - мержу - второй удаляется и вываливается exception, мол не могу добавить row - нет такой записи, то есть где то в кеше осталась запись о том первом item, который я удалил первый и hibernate попытался записать его в базу - что не есть правильно впринципе, и вообще merge это немного не решение моей проблемы.
Также я немного больше получил понимание по первому Exception'y:
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.test.User#2d0767d8-effb-41f2-8910-5729a460527d]
Вся суть в том что, объект user - это залогиненный пользователь полученный при помощи собственной аннотации, которую я повесил на контроллер. То есть, в контроллере есть аннтотация которая получается залогиненного пользователя, естественно что она получает его при помощи hibernate (не явно конечно, долго объяснять, а код показываться - отклонятся от темы вопроса), так вот, полученный объект пользователя из контроллера я и передаю в метод удаления детеныша из родителя. То есть получается что hibernate видит в persistent сессии тот самый объект с 3 детьми, а тут я ему подсовываю другой объект с 2 детьми уже, а они по какой-то дикой причине разные!!! Я попробовал еще раз вытянуть из базы пользователя и у него удалить детеныша - удалилось, да только вот сущность которая представляет собой залогированного пользователя осталась неизменной.