I have two entity classes Organisation and User with a One To Many relationship (Groovy Code for simplicity!):
@Entity
class Organisation {
@Id Long id
String name
@OneToMany
List<User> users
}
@Entity
class User {
@Id Long id
String username
@ManyToOne(optional=false, cascade = CascadeType.Persist)
Organisation organisation
}
When I create a new user with a new organisation everything works fine:
def user = new User(organisation: new Organisation(...))
But when I take an existing organisation, set it to the organisation attribute to a new user I get an error:
def user = new User(organisation: organisationRepository.findOne(orgId))
userRepo.save(user)
Will result in:
org.hibernate.PersistentObjectException: detached entity passed to persist: Organisation
I know that one cannot call persist on a detached entity. But in that case, since I don't change anything on the organisation entity itself, I thought hibernate would permit it.
I tried to put cascade = {CascadeType.Persist, CascadeType.Merge} into the ManyToOne annotation, but that ends in the same error.
Is the thing I want to archive not possible with hibernate or do I have a thinking error somewhere?
You were going in the right direction with:
cascade = {CascadeType.Persist, CascadeType.Merge}
The thing is that when you still perform save operation, the persistence provider tries to cascade the persist operation, so it ends up trying to persist the Organization entity which already has an @Id set up and is detached.
What you would have to do is perform merge instead of save.
In that case the new entity will be persisted and the Organization will be merged back into the persistence context, hence allowing the whole operation to be successful.
Just keep in mind that when you use merge and want to perform operations on the passed entity afterwards, you would need to assign the result to a new variable and perform operation on it f.e.:
User mergedUser = userRepo.merge(user);
// operations on mergedUser from now on