Jump to: navigation, search

EclipseLink/Development/JPA 2.0/mappedbyid

MappedById Support

JPA 2.0 Root | Enhancement Request

Issue Summary

In JPA 1.0 primary key columns could only be mapped to @Basic attributes. Primary Keys that were derived from Foreign Keys had to be mapped twice, once as the relationship mapping and again as an @Basic. JPA 2.0 adds the functionality to designate a Relationship as providing the primary key for an Entity, see | DerivedId . When using an embeddedid, a @MappedById annotation can be used on a relationship mapping to indicate that it uses the same Id field that is also defined by the target ID field in the Embeddedid.

See JPA 2.0 section 2.4.1 for details.

General Solution

The EmbeddedID will be difficult to support as values in the EmbeddedID will need to be populated by EclipseLink on persist(), merge() calls even though they are not the sources of Identity for the Entity. Even more complicated if the derived ID is an IdClass then an instance of that class must be stored in the EmbeddedId which will be new functionality in EclipseLink. Transformation Mapping may be leveraged in combination with the CMP3Policy to support this functionality.

Metadata processing

The metadata processing will need a number of changes to support the notion of id classes and embedded id classes within their own embedded id's. The spec provided 6 examples, so we'll work through each and discuss the metadata processing behevior and any changes needed to it.

Example 1

The parent entity has a simple primary key and the dependent entity uses EmbeddedId to represent a composite key.

@Entity
@Table(name="JPA_SARGEANT")
public class Sargeant {
    @Id
    @Column(name="ID")
    @GeneratedValue(strategy=TABLE, generator="SARGEANT_TABLE_GENERATOR")
    @TableGenerator(
        name="SARGEANT_TABLE_GENERATOR", 
        table="JPA_SARGEANT_SEQ", 
        pkColumnName="SEQ_NAME", 
        valueColumnName="SEQ_COUNT",
        pkColumnValue="SARGEANT_SEQ",
        initialValue=50
    )
    long sargeantId;

    @Basic
    @Column(name="NAME")
    String name;
    
    public String getName() {
        return name;
    }
    
    public long getSargeantId() {
        return sargeantId;
    }

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

@Entity
@Table(name="JPA_MASTER_CORPORAL")
public class MasterCorporal {
    @EmbeddedId 
    MasterCorporalId id;
    
    @ManyToOne 
    @MappedById("sargeantPK")
    Sargeant sargeant;
    
    public MasterCorporalId getId() {
        return id;
    }
    
    public Sargeant getSargeant() {
        return sargeant;
    }
    
    public void setId(MasterCorporalId id) {
        this.id = id;
    }

    public void setSargeant(Sargeant sargeant) {
        this.sargeant = sargeant;
        id.setSargeantPK(sargeant.getSargeantId());
    }
}

@Embeddable
public class MasterCorporalId {
    @Column(name="NAME")
    String name;
    
    @Column(name="SARGEANTPK")
    long sargeantPK;
    
    public String getName() {
        return name;
    }
    
    public long getSargeantPK() {
        return sargeantPK;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void setSargeantPK(long sargeantPK) {
        this.sargeantPK = sargeantPK;
    }
}

Work Required

  1. Develop model for testing access type settings
    approx ? days
  2. Update Processing
    approx ? days