How to persist @ManyToMany relation - duplicate entry or detached entity

后端 未结 5 1930
一整个雨季
一整个雨季 2020-12-01 06:36

I want to persist my entity with ManyToMany relation. But i have some problem during persisting process.

My entities :

@Entity
@Table(name = \"USER\"         


        
5条回答
  •  情话喂你
    2020-12-01 07:17

    I will provide my answer if anyone get same type of problem to me and the author.

    Basically what I was facing was a situation when I had one table which was some kind of CONSTANT values. And the other would change, but it should map (many to many) to those CONSTANTS.

    The exact problem is USERS and it's ROLES.

    Roles would be known and added on system startup, thus they should never get removed. Even if no user would have some Role it should still be in the system.

    The class implementation, using JPA:

    User:

    @Entity
    @Table(name = "USERS")
    public class User{
    
        @Id
        private String login;
        private String name;
        private String password;
    
        @ManyToMany(cascade = {CascadeType.MERGE})
        private Set roles = new HashSet<>();
    

    Role:

    @Entity
    @Table(name = "ROLE")
    public class Role {
    
        @Id
        @Enumerated(value = EnumType.STRING)
        private RoleEnum name;
    
        @ManyToMany(mappedBy = "roles")
        private Set users = new HashSet<>();
    

    Usage

    This setup will easily add/remove Role to User. Simply by passing an array, f.e.: user.getRoles().add(new Role("ADMIN")); and merge the user. Removing works with passing an empty list.

    If you forget to add the Role before adding it to the user most likely you will get an error like:

    javax.persistence.RollbackException: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: com.storage.entities.Role@246de37e.
    

    What and why

    • mappedBy attribute is added to the child Entity as described in the JPA Docs

    If you choose to map the relationship in both directions, then one direction must be defined as the owner and the other must use the mappedBy attribute to define its mapping (...)

    • cascade = {CascadeType.MERGE} is added for proper cascades JPA Docs

    Cascaded the EntityManager.merge() operation. If merge() is called on the parent, then the child will also be merged. This should normally be used for dependent relationships. Note that this only affects the cascading of the merge, the relationship reference itself will always be merged.

提交回复
热议问题