如何在沒有 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}),否則如果刪除子項,你的父資料將被刪除