Возможный дубликат Обновление против слияния
Что здесь происходит: Режим редактирования:
List<UserRole> roles = entity.getRoles(); //Gets Existing Roles from DB
for(UserRole r : roles) {
Em.get().remove(r); //Removes Roles to existing user
}
roles.clear(); // Clean up local memory
for(RoleEnum r : selectedRoles) { // User Input Roles
UserRole role = new UserRole(entity, r); // New Entity with existing user
Em.get().persist(role); // Role Entity Referenced to existing user object, saved
}
Em.get().merge(entity); // ?? No Need in edit unless roles are stored in user table
Em.get().flush();
Новый пользовательский режим:
List<UserRole> roles = entity.getRoles(); // New Detached User Entity Roles
for(UserRole r : roles) { // Probably Empty Roles Array
Em.get().remove(r); // Removed roles
}
roles.clear(); // Clean up Memory
for(RoleEnum r : selectedRoles) { // Copy from App Roles
UserRole role = new UserRole(entity, r); //Create new role
Em.get().persist(role); //Save Role to DB
}
Em.get().merge(entity); // Trying to merge non existing Entity <-- This is where error appears
Em.get().flush();
Метод persist работает, потому что он решает, когда использовать команду вставки или обновления. Поскольку для нового пользовательского объекта не задан идентификатор, он не знает, что с ним делать, хотя, возможно, он работал в прошлом, фактическое поведение mergig очень хорошо объяснено в этой теме объединение отдельного или нового объекта с существующая сущность в hibernate / jpa: вопрос передовой практики
Убедитесь сами:
Если ваша сущность является отдельной сущностью, единственное, что вам действительно нужно сделать, - это вызвать entityManager.merge (пользователь). Вам не нужно выполнять c любой метод поиска. Если ваша сущность не отделена, а скорее нова (для нее не указан идентификатор), вы должны найти соответствующую сущность в базе данных до выполнения каких-либо операций по изменению этой сущности и затем объединить ее.
Еще одна подробная ссылка здесь: persist () и merge () в JPA и Hibernate
Вот ссылка из документов:
Сериализуемый save (Object объект) выдает HibernateException
Persist the given transient instance, first assigning a generated identifier. (Or using the current value of the identifier property if the assigned generator is used.) This operation cascades to associated instances if the association is mapped with cascade="save-update".
Parameters:
object - a transient instance of a persistent class
Returns:
the generated identifier
Throws:
HibernateException
сохраняется
void persist (String entityName, Object object) выдает HibernateException
Make a transient instance persistent. This operation cascades to associated instances if the association is mapped with cascade="persist".
The semantics of this method are defined by JSR-220.
Parameters:
object - a transient instance to be made persistent
Throws:
HibernateException
объединить
Слияние объектов (String entityName, Object object) генерирует HibernateException
Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade="merge".
The semantics of this method are defined by JSR-220.
Parameters:
object - a detached instance with state to be copied
Returns:
an updated persistent instance
Throws:
HibernateException
save () и persist () в результате SQL INSERT, delete () в SQL DELETE и update () или merge () в SQL UPDATE. Изменения в постоянных случаях обнаруживаются во время гриппа sh и также приводят к SQL ОБНОВЛЕНИЮ. saveOrUpdate () и replicate () приводят либо к INSERT, либо к UPDATE.
Вывод: функции ведут себя так, как они предназначены.