JPA composite primary key from foreign keys with property access

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

Apparently there is no question about how to create a composite primary key from foreign keys in a property access way.

Question

If I use the property access type as in the example below, do I have to define getters and setters for the referenced FKs as well ?

I did not think that that's the case but the official documentation of Java EE6 does so.

Oracle® Containers for J2EE Enterprise JavaBeans Developer's Guide

A composite primary key class has the following characteristics:

  • It is a POJO class.
  • It must be public and must have a public no-argument constructor.
  • If you use property-based access, the properties of the primary key class must be public or protected.
  • It must be serializable.
  • It must define equals and hashCode methods.
  • The semantics of value equality for these methods must be consistent with the database equality for the database types to which the key is mapped.
  • You can make the composite primary key class either an embedded class owned by the entity class, or a nonembedded class whose fields you map to multiple fields or properties of the entity class. In the latter case, the names of primary key fields or properties in the composite primary key class and those of the entity class must correspond and their types must be the same.

    I modified this example because I want to use FKs.

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

    JPA Spec (2.3.2) - Explicit Access Type

    When Access(PROPERTY) is applied to an entity class , mapped superclass, or embeddable class, mapping annotations may be placed on the properties of that class, and the persistence provider runtime accesses persistent state via the properties defined by that class . All properties that are not annotated with the Transient annotation are persistent. When Access(PROPERTY) is applied to such a class, it is possible to selectively designate individual attributes within the class for instance variable access. To specify a persistent instance variable for access by the persistence provider runtime, that instance variable must be designated Access(FIELD) . The behavior is undefined if mapping annotations are placed on any instance variables defined by the class for which Access(FIELD) is not specified . Persistent state inherited from superclasses is accessed in accordance with the access types of those superclasses.

    JPA Spec (2.3.3) - Access Type of an Embeddable Class

    The access type of an embeddable class is determined by the access type of the entity class , mapped superclass, or embeddable class in which it is embedded (including as a member of an element collection) independent of whether the access type of the containing class has been explicitly specified or defaulted. A different access type for an embeddable class can be specified for that embeddable class by means of the Access annotation as described above.

    When the AccessType is set to PROPERTY for an entity class, the provider will use the methods to get the persistent state and mapping data. The persistence provider is not obligated to look for mapping annotations on fields when the AccessType for the class is PROPERTY. Also, note that AccessType is inherited by the Embedded class, which is why EmployeePK needs to define the getters/setters as well. Based on what it says in the spec, when the entity class is using Access(PROPERTY), you should do one of the following:

  • Define getter/setter methods for the FK fields and place the mappings on the getter methods

    Example:

    @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;
        }
    }
    
  • Or, explicitly define Access(FIELD) on the persistent field

    Example:

    @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;
        }
    }
    
  • 链接地址: http://www.djcxy.com/p/37012.html

    上一篇: 线ggplot2周围的缓冲区

    下一篇: 来自具有属性访问权的外键的JPA复合主键