【问题标题】:Using a composite key in a many-to-many relationship in JPA在 JPA 中的多对多关系中使用复合键
【发布时间】:2011-01-23 03:22:28
【问题描述】:

我遇到以下情况:

  • 用户对象具有一组权限对象 (Set<Permission>)
  • 每个用户可以拥有零个或多个权限
  • 一个 Permission 对象具有三个字段
  • 权限的三个字段组成复合 该权限的密钥。
  • 因此,我们希望 每个权限的数据库中的一个实例。每个用户都可能 拥有相同的权限。
  • 因此用户对象有一个 与 Permission 的多对多关系。

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

有什么想法吗?

【问题讨论】:

    标签: java hibernate database-design jpa


    【解决方案1】:

    一个 Permission 对象具有三个字段

    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     
            }
    
        }
    
    }
    

    问候,

    【讨论】:

      猜你喜欢
      • 2015-12-13
      • 1970-01-01
      • 2019-10-01
      • 1970-01-01
      • 2020-03-03
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多