首页 文章

具有属性访问权限的外键的JPA复合主键

提问于
浏览
0

I'm a novice in JPA please stay with me.

显然,如何在属性访问方式中从外键创建复合主键是毫无疑问的 .

Question

如果我使用属性访问类型,如下例所示,我是否还必须为引用的FK定义getter和setter?

我不认为那是这种情况,但Java EE6的official documentation是这样的 .

Oracle® Containers for J2EE Enterprise JavaBeans Developer's Guide

复合主键类具有以下特征:它是POJO类 . 它必须是公共的,并且必须具有公共无参数构造函数 . 如果使用基于属性的访问,则主键类的属性必须是公共的或受保护的 . 它必须是可序列化的 . 它必须定义equals和hashCode方法 . 这些方法的值相等的语义必须与键映射到的数据库类型的数据库相等性一致 . 您可以使复合主键类成为实体类拥有的嵌入类,或者将非字符串类映射到实体类的多个字段或属性 . 在后一种情况下,复合主键类中的主键字段或属性的名称以及实体类的名称必须对应,并且它们的类型必须相同 .

我修改了这个例子,因为我想使用FK .

Example 7-2 Embeddable Composite Primary Key Class

@Embeddable
public class EmployeePK implements Serializable {
    private String name;
    private long id;

    public EmployeePK() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public int hashCode() {
        return (int) name.hashCode() + id;
    }

    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof EmployeePK)) return false;
        if (obj == null) return false;
        EmployeePK pk = (EmployeePK) obj;
        return pk.id == id && pk.name.equals(name);
    }
}

Example 7-3 JPA Entity With an Embedded Composite Primary Key Class

@Entity
@Access(AccessType.PROPERTY)
public class Employee implements Serializable {
    EmployeePK primaryKey;

    public Employee() {
    }

    @EmbeddedId
    public EmployeePK getPrimaryKey() {
        return primaryKey;
    }

    public void setPrimaryKey(EmployeePK pk) {
        primaryKey = pk;
    }

    @ManyToOne
    @MapsId("id")
    private classWithPKid fkobject1;

    @ManyToOne
    @MapsId("name")
    private classWithPKname fkobject2;
    ...
}

1 回答

  • 1

    JPA Spec(2.3.2) - 显式访问类型

    当Access(PROPERTY)应用于实体类,映射的超类或可嵌入类时,映射注释可以放在该类的属性上,持久性提供程序运行时通过该类定义的属性访问持久状态 . 未使用Transient注释注释的所有属性都是持久的 . 当Access(PROPERTY)应用于这样的类时,可以选择性地指定类中的各个属性,例如变量访问 . 要指定持久性提供程序运行时访问的持久性实例变量,必须将该实例变量指定为Access(FIELD) . 如果将映射注释放在由未指定Access(FIELD)的类定义的任何实例变量上,则行为未定义 . 从超类继承的持久状态是根据这些超类的访问类型访问的 .

    JPA规范(2.3.3) - 可嵌入类的访问类型

    可嵌入类的访问类型由实体类的访问类型,映射的超类或嵌入它的嵌入类(包括作为元素集合的成员)决定,与是否包含类的访问类型无关已明确指定或默认 . 可以通过如上所述的Access注释为该可嵌入类指定可嵌入类的不同访问类型 .

    当AccessType设置为实体类的PROPERTY时,提供程序将使用这些方法来获取持久状态和映射数据 . 当类的AccessType为PROPERTY时,持久性提供程序没有义务在字段上查找映射注释 . 另请注意,AccessType是由Embedded类继承的,这也是EmployeePK也需要定义getter / setter的原因 . 根据规范中的内容,当实体类使用Access(PROPERTY)时,您应该执行以下操作之一:

    • 为FK字段定义getter / setter方法,并将映射放在getter方法上

    例:

    @Entity
    @Access(AccessType.PROPERTY)
    public class Employee {
        private EmployeePK primaryKey;
    
        private ClassWithPKid fkobject1;
    
        @EmbeddedId
        public EmployeePK getPrimaryKey() {
            return primaryKey;
        }
    
        @ManyToOne
        @MapsId("id")
        public ClassWithPKid getFkobject1() {
            return fkobject1;
        }
    }
    
    • 或者,在持久字段上显式定义Access(FIELD)

    例:

    @Entity
    @Access(AccessType.PROPERTY)
    public class Employee {
        private EmployeePK primaryKey;
    
        @ManyToOne
        @MapsId("id")
        @Access(AccessType.FIELD)
        private ClassWithPKid fkobject1;
    
        @EmbeddedId
        public EmployeePK getPrimaryKey() {
            return primaryKey;
        }
    }
    

相关问题