how to make a composite primary key (java persistence annotation)

前端 未结 5 1056
天命终不由人
天命终不由人 2020-11-29 06:05

How to make it so that the table user_roles defines the two columns (userID, roleID) as a composite primary key. should be easy, just can\'t remember/find.

In

5条回答
  •  爱一瞬间的悲伤
    2020-11-29 06:36

    In order to fulfill your requirement, you can map your @ManyToMany as a @OneToMany mapping. This way, USER_ROLE will contain both USER_ID and ROLE_ID as compound primary key

    I will show you how to:

    @Entity
    @Table(name="USER")
    public class User {
    
        @Id
        @GeneratedValue
        private Integer id;
    
        @OneToMany(cascade=CascadeType.ALL, mappedBy="joinedUserRoleId.user")
        private List joinedUserRoleList = new ArrayList();
    
        // no-arg required constructor
        public User() {}
    
        public User(Integer id) {
            this.id = id;
        }
    
        // addRole sets up bidirectional relationship
        public void addRole(Role role) {
            // Notice a JoinedUserRole object
            JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(this, role));
    
            joinedUserRole.setUser(this);
            joinedUserRole.setRole(role);
    
            joinedUserRoleList.add(joinedUserRole);
        }
    
    }
    
    @Entity
    @Table(name="USER_ROLE")
    public class JoinedUserRole {
    
        public JoinedUserRole() {}
    
        public JoinedUserRole(JoinedUserRoleId joinedUserRoleId) {
            this.joinedUserRoleId = joinedUserRoleId;
        }
    
        @ManyToOne
        @JoinColumn(name="USER_ID", insertable=false, updatable=false)
        private User user;
    
        @ManyToOne
        @JoinColumn(name="ROLE_ID", insertable=false, updatable=false)
        private Role role;
    
        @EmbeddedId
        // Implemented as static class - see bellow
        private JoinedUserRoleId joinedUserRoleId;
    
        // required because JoinedUserRole contains composite id
        @Embeddable
        public static class JoinedUserRoleId implements Serializable {
    
            @ManyToOne
            @JoinColumn(name="USER_ID")
            private User user;
    
            @ManyToOne
            @JoinColumn(name="ROLE_ID")
            private Role role;
    
            // required no arg constructor
            public JoinedUserRoleId() {}
    
            public JoinedUserRoleId(User user, Role role) {
                this.user = user;
                this.role = role;
            }
    
            public JoinedUserRoleId(Integer userId, Integer roleId) {
                this(new User(userId), new Role(roleId));
            }
    
            @Override
            public boolean equals(Object instance) {
                if (instance == null)
                    return false;
    
                if (!(instance instanceof JoinedUserRoleId))
                    return false;
    
                final JoinedUserRoleId other = (JoinedUserRoleId) instance;
                if (!(user.getId().equals(other.getUser().getId())))
                    return false;
    
                if (!(role.getId().equals(other.getRole().getId())))
                    return false;
    
                return true;
            }
    
            @Override
            public int hashCode() {
                int hash = 7;
                hash = 47 * hash + (this.user != null ? this.user.hashCode() : 0);
                hash = 47 * hash + (this.role != null ? this.role.hashCode() : 0);
                return hash;
            }
    
        }
    
    }
    

    remember

    If an object has an assigned identifier, or a composite key, the identifier SHOULD BE ASSIGNED to the object instance BEFORE calling save().

    So we have created a JoinedUserRoleId constructor like this one in order to take care of it

    public JoinedUserRoleId(User user, Role role) {
        this.user = user;
        this.role = role;
    }
    

    And finally Role class

    @Entity
    @Table(name="ROLE")
    public class Role {
    
        @Id
        @GeneratedValue
        private Integer id;
    
        @OneToMany(cascade=CascadeType.ALL, mappedBy="JoinedUserRoleId.role")
        private List joinedUserRoleList = new ArrayList();
    
        // no-arg required constructor
        public Role() {}
    
        public Role(Integer id) {
            this.id = id;
        }
    
        // addUser sets up bidirectional relationship
        public void addUser(User user) {
            // Notice a JoinedUserRole object
            JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(user, this));
    
            joinedUserRole.setUser(user);
            joinedUserRole.setRole(this);
    
            joinedUserRoleList.add(joinedUserRole);
        }
    
    }
    

    According to test it, let's write the following

    User user = new User();
    Role role = new Role();
    
    // code in order to save a User and a Role
    Session session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();
    
    Serializable userId  = session.save(user);
    Serializable roleId = session.save(role);
    
    session.getTransaction().commit();
    session.clear();
    session.close();
    
    // code in order to set up bidirectional relationship
    Session anotherSession = HibernateUtil.getSessionFactory().openSession();
    anotherSession.beginTransaction();
    
    User savedUser = (User) anotherSession.load(User.class, userId);
    Role savedRole = (Role) anotherSession.load(Role.class, roleId);
    
    // Automatic dirty checking
    // It will set up bidirectional relationship
    savedUser.addRole(savedRole);
    
    anotherSession.getTransaction().commit();
    anotherSession.clear();
    anotherSession.close();
    

    Notice according to code above NO REFERENCE to JoinedUserRole class.

    If you want to retrieve a JoinedUserRole, try the following

    Session session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();
    
    Integer userId;
    Integer roleId;
    
    // Lets say you have set up both userId and roleId
    JoinedUserRole joinedUserRole = (JoinedUserRole) session.get(JoinedUserRole.class, new JoinedUserRole.JoinedUserRoleId(userId, roleId));
    
    // some operations
    
    session.getTransaction().commit();
    session.clear();
    session.close();
    

    regards,

提交回复
热议问题