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

时间:2017-02-15 16:14:32

标签: java jpa eclipselink

我是JPA的新手请留下来。

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

问题

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

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

Oracle® Containers for J2EE Enterprise JavaBeans Developer's Guide

  

复合主键类具有以下特征:

     
      
  • 这是一个POJO课程。
  •   
  • 它必须是公共的,并且必须有一个公共的无参数构造函数。
  •   
  • 如果您使用基于属性的访问权限,则主键类的属性必须是公共的或受保护的。
  •   
  • 必须是可序列化的。
  •   
  • 必须定义equals和hashCode方法。
  •   
  • 这些方法的值相等的语义必须与键映射到的数据库类型的数据库相等一致。
  •   
     

您可以将复合主键类设置为嵌入类   由实体类拥有,或者是您映射其字段的非嵌入类   到实体类的多个字段或属性。在后者   case,复合中主键字段或属性的名称   主键类和实体类的必须对应和   他们的类型必须相同。

我修改了这个例子,因为我想使用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 个答案:

答案 0 :(得分:1)

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

  

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

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

  

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

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

  1. 为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;
        }
    }
    
  2. 或者,在持久字段

    上明确定义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;
        }
    }