Search code examples
jpaentitycascadepersist

Will JPA try to cascade persist and already persistent entity?


Will JPA try to cascade persist on an entity that is already persistent (and non-detached)?

To make things clear, here's my situation: I want to persist a new User:

public void addUser(){
    //User is an entity that is related to many Groups
    //The relationship on User side is marked with cascade persist
    User user = new User();
    user.setName("foo");
    user.setGroups(new ArrayList<Groups>());

    //selectedGroups is an List of Groups previously created with persistent Groups
    for(Group g : this.selectedGroups){
        user.getGroups().add(this.groupDao.find(g.getId()));
    }
    //At this point, User.getGroups() is a list of Managed Entities

    //What happens on the following line?
    userDao.persist(user);
}

So, what happens? Will JPA try to persist (again) every single group in user.getGroups()? Or will it detect that those groups already exist and just update new relations?

In case of 'Yes, it will persist again', how should I annotate this relation to make that code work properly?


Solution

  • JPA will detect the difference between new groups and already persisted groups and will only persist new groups.

    edit: in response to comments

    JPA probably tries to persist them again because they have been detached. This means you either have to attach them again using merge or prevent them from being detached.

    The most likely reason for them becoming detached is the end of the transaction they were part of. Assuming you are using JTA and did nothing extra then if addUser is not a method of an EJB while groupDao is an EJB then the transaction starts with the groupDao.find call and ends the moment find returns. Because by default an EJB method starts a transaction if not one is already running. If addUser is a method of an EJB things should be fine because then addUser will start the transaction and groupDao.find will use the existing transaction so everything happens in one transaction.