3

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?

SakeSushiBig
  • 1,481
  • 2
  • 14
  • 20
  • Possible duplicate of [JPA/Hibernate: detached entity passed to persist](http://stackoverflow.com/questions/13370221/jpa-hibernate-detached-entity-passed-to-persist) – agilob Mar 20 '17 at 15:56
  • You have to manage database relation in better way, find out more here https://stackoverflow.com/questions/13370221/jpa-hibernate-detached-entity-passed-to-persist – agilob Mar 20 '17 at 15:56

1 Answers1

1

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
Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
  • 1
    Hi, thanks for the quick response! :) Since I use Spring Framework and the JpaRepository class I don't have a merge method there. Does that mean I have to use some hibernate internal repository class? Like EntityManager? Or do you maybe now if Spring Repos also provide some merge function. I browsed through the docs quickly but didn't find anything. – SakeSushiBig Mar 20 '17 at 16:20
  • And can I even call merge on a new entity? – SakeSushiBig Mar 20 '17 at 16:28
  • Yes, it will support creation of new entity. You have to keep in mind though that merge is a bit more expensive operation than persist. You may consider doing the merge on organization and then persist on the user. If you dont care and want to do all in one go then follow my answer. – Maciej Kowalski Mar 20 '17 at 16:35