如何在没有 Embeddable 注释的情况下处理复合键

如果你有

Role:
+-----------------------------+
| `roleId` | name | discription |
+-----------------------------+

Rights:
+-----------------------------+
| `rightId` | name | discription|
+-----------------------------+

rightrole
+------------------+
| `roleId` | rightId | 
+------------------+

在上面的场景中,rightrole 表有复合键并且在 JPA 中访问它时用户必须使用 Embeddable 注释创建实体。

像这样:

rightrole 表的实体是:

    @Entity
    @Table(name = "rightrole")
    public class RightRole extends BaseEntity<RightRolePK> {
    
        private static final long serialVersionUID = 1L;
    
        @EmbeddedId
        protected RightRolePK rightRolePK;

    
        @JoinColumn(name = "roleID", referencedColumnName = "roleID", insertable = false, updatable = false)
        @ManyToOne(fetch = FetchType.LAZY)
        private Role role;
    
        @JoinColumn(name = "rightID", referencedColumnName = "rightID", insertable = false, updatable = false)
        @ManyToOne(fetch = FetchType.LAZY)
        private Right right;

        ......
     }

    @Embeddable
    public class RightRolePK implements Serializable {
    private static final long serialVersionUID = 1L;

      @Basic(optional = false)
      @NotNull
      @Column(nullable = false)
      private long roleID;

      @Basic(optional = false)
      @NotNull
      @Column(nullable = false)
     private long rightID;

   .....

}

可嵌入的注释适用于单个对象,但在插入批量记录时会出现问题。

问题是每当用户想要用 rights 创建新的 role 然后第一个用户必须使用 store(persist) role 对象然后用户必须做 flush 来获得新生成的 id 用于角色。然后用户可以把它放在 rightrole 实体的对象中。

要解决这个用户可以写实体略有不同的方式。

角色表的实体是:

@Entity
@Table(name = "role")
public class Role {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @NotNull
    @Column(nullable = false)
    private Long roleID;

    
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "role", fetch = FetchType.LAZY)
    private List<RightRole> rightRoleList;
 
    @ManyToMany(cascade = {CascadeType.PERSIST})
    @JoinTable(name = "rightrole",
            joinColumns = {
                @JoinColumn(name = "roleID", referencedColumnName = "ROLE_ID")},
            inverseJoinColumns = {
                @JoinColumn(name = "rightID", referencedColumnName = "RIGHT_ID")})
    private List<Right> rightList;
.......
}

即使没有实体,@joinTable 注释也会在 rightrole 表中插入(只要该表只有 role 和 right 的 id 列)。

用户可以简单地:

Role role = new  Role();
List<Right> rightList = new ArrayList<>();
Right right1 = new Right();
Right right2 = new Right();
rightList.add(right1);
rightList.add(right2);
role.setRightList(rightList);

你必须在 inverseJoinColumns 中编写 @ManyToMany(cascade = {CascadeType.PERSIST}),否则如果删除子项,你的父数据将被删除