在JPA中使用多对多关系中的复合键

时间:2010-03-03 10:16:42

标签: java hibernate database-design jpa

我遇到以下情况:

  • 用户对象具有一组权限对象(Set<Permission>
  • 每个用户可以拥有零个或多个权限
  • Permission对象有三个字段
  • 权限的三个字段组成了复合词 该权限的关键。
  • 因此,我们完全想要 每个权限的DB中的一个实例。每个用户都可以 拥有相同的权限。
  • 因此,User对象具有 与权限的多对多关系。

问题是:在这种情况下,我如何使Permission实体成为自身的复合键?在这种多对多关系的背景下,我特别感兴趣。

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

Permission对象有三个字段

权限的三个字段构成复合键

属性和复合主键共享相同的列

所以你的问题看起来像这个

@Entity
public class Permission {

    private PermissionId permissionId;

    private Integer field1;
    private Integer field2;
    private Integer field3;

    // required no-arg constructor   
    public Permission() {}

    public Permission(Integer field1, Integer field2, Integer field3) {
        this.field1 = field1;
        this.field2 = field2;
        this.field3 = field3;

        setPermissionId(new PermissonId(Integer field1, Integer field2, Integer field3));
    }

    @EmbeddedId
    public PermissionId getPermissionId() {
        return this.permissionId;
    }

    @Column(name="FIELD_1", insertable=false, updatable=false)
    public Integer getField1() {
        return this.field1;
    }

    @Column(name="FIELD_2", insertable=false, updatable=false)
    public Integer getField2() {
        return this.field2;
    }

    @Column(name="FIELD_3", insertable=false, updatable=false)
    public Integer getField3() {
        return this.field3;
    }

    @Embeddable
    public static class PermissionId implements Serializable {

        private Integer field1;
        private Integer field2;
        private Integer field3;

        // required no-arg constructor
        public PermissionId() {}

        public PermissionId(Integer field1, Integer field2, Integer field3) {
            this.field1 = field1;
            this.field2 = field2;
            this.field3 = field3;
        }

        @Column(name="FIELD_1", nullable=false)
        public Integer getField1() {
            return this.field1;
        }

        @Column(name="FIELD_2", nullable=false)
        public Integer getField2() {
            return this.field2;
        }

        @Column(name="FIELD_3", nullable=false)
        public Integer getField3() {
            return this.field3;
        }

        public boolean equals(Object o) {
            if(o == null) 
                return false;

            if(!(o instanceof PermissionId))
                return false;

            final PermissionId other = (PermissionId) o;

            if(!(getField1().equals(other.getField1()))) 
                return false;

            if(!(getField2().equals(other.getField2()))) 
                return false;

            if(!(getField3().equals(other.getField3()))) 
                return false;

            return true;
        }

        // requered hashcode impl
        public int hashcode() {
            // code goes here     
        }

    }

}

但别忘了

  

由于多个属性共享同一列,因此您必须将其中一个定义为insertable = false,updatable = false。否则,Hibernate会抱怨一些错误。

  

如果您有复合主键,则必须设置其值。 Hibernate不支持自动生成复合主键。

如果您不喜欢上述方法,可以执行以下操作

@Entity
@IdClass(PermissionId.class)
public class Permission {

    private Integer field1;
    private Integer field2;
    private Integer field3;

    // required no-arg constructor   
    public Permission() {}

    public Permission(Integer field1, Integer field2, Integer field3) {
        this.field1 = field1;
        this.field2 = field2;
        this.field3 = field3;
    }

    @Id
    @Column(name="FIELD_1", nullable=false)
    public Integer getField1() {
        return this.field1;
    }

    @Id
    @Column(name="FIELD_2", nullable=false)
    public Integer getField2() {
        return this.field2;
    }

    @Id
    @Column(name="FIELD_3", nullable=false)
    public Integer getField3() {
        return this.field3;
    }

    @Embeddable
    public static class PermissionId implements Serializable {

        private Integer field1;
        private Integer field2;
        private Integer field3;

        // required no-arg constructor
        public PermissionId() {}

        public PermissionId(Integer field1, Integer field2, Integer field3) {
            this.field1 = field1;
            this.field2 = field2;
            this.field3 = field3;
        }

        @Column(name="FIELD_1")
        public Integer getField1() {
            return this.field1;
        }

        @Column(name="FIELD_2")
        public Integer getField2() {
            return this.field2;
        }

        @Column(name="FIELD_3")
        public Integer getField3() {
            return this.field3;
        }

        public boolean equals(Object o) {
            if(o == null) 
                return false;

            if(!(o instanceof PermissionId))
                return false;

            final PermissionId other = (PermissionId) o;

            if(!(getField1().equals(other.getField1()))) 
                return false;

            if(!(getField2().equals(other.getField2()))) 
                return false;

            if(!(getField3().equals(other.getField3()))) 
                return false;

            return true;
        }

        // requered hashcode impl
        public int hashcode() {
            // code goes here     
        }

    }

}

的问候,