开发者

Using a composite key in a many-to-many relationship in JPA

I've got the following situation:

  • A User object has a Set of Permission objects (Set<Permission>)
  • Each User can have zero or more Permissions
  • A Permission object has three fields
  • The three fields of Permission make up the composite key for that permission.
  • 开发者_如何学GoAs a consequence of this, we want exactly one instance in the DB of each Permission. Each user can potentially have the same Permission.
  • The User object therefore has a many-to-many relationship with Permission.

The question is: how, in this situation, do I make the Permission entity a composite key of itself? I'm particularly interested in doing this in the context of this many-to-many relationship.

Any ideas?


A Permission object has three fields

The three fields of Permission up make up the composite key

Both property and compound primary keys share the same columns

So Your question looks like this one

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

    }

}

But do not forget

Because more than one property share the same column, you have to define one of them as insertable=false, updatable=false. Otherwise, Hibernate will complain some errors.

And

When you have a compound primary key, you have to set up its values. Hibernate does not support automatic generation of compound primary key.

But if you do not like the approach as shown above, you can do the following one

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

    }

}

regards,

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜