JPA 将具有 PK 的实体映射到具有复合 PK 的实体
JPA Map Entity with PK to Entity with Composite PK
注意:我是 JPA 开发的新手,正在学习 trial by fire,所以请原谅我可能遗漏的任何明显内容。
这是相关的 JPA 实体。地址未列出,但它是一个非常简单的实体,具有一个名为 id 的 @Id。
ShipTo.java
package model;
import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;
import java.sql.Timestamp;
/**
* The persistent class for the ship_to database table.
*
*/
@Entity
@Table(name="ship_to")
@NamedQuery(name="ShipTo.findAll", query="SELECT s FROM ShipTo s")
public class ShipTo implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private ShipToPK id;
//bi-directional many-to-one association to Customer
@ManyToOne
@JoinColumns({
@JoinColumn(name="company_id", referencedColumnName="company_id"),
@JoinColumn(name="customer_id", referencedColumnName="customer_id")
})
private Customer customer;
//bi-directional one-to-one association to Address
@OneToOne
@JoinColumn(name="ship_to_id", referencedColumnName="id")
private Address address;
ShipToPK.java
package model;
import java.io.Serializable;
import javax.persistence.*;
/**
* The primary key class for the ship_to database table.
*
*/
@Embeddable
public class ShipToPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(name="company_id", insertable=false, updatable=false)
private String companyId;
@Column(name="ship_to_id")
private long shipToId;
public ShipToPK() {
}
public String getCompanyId() {
return this.companyId;
}
public void setCompanyId(String companyId) {
this.companyId = companyId;
}
public long getShipToId() {
return this.shipToId;
}
public void setShipToId(long shipToId) {
this.shipToId = shipToId;
}
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof ShipToPK)) {
return false;
}
ShipToPK castOther = (ShipToPK)other;
return
this.companyId.equals(castOther.companyId)
&& (this.shipToId == castOther.shipToId);
}
public int hashCode() {
final int prime = 31;
int hash = 17;
hash = hash * prime + this.companyId.hashCode();
hash = hash * prime + ((int) (this.shipToId ^ (this.shipToId >>> 32)));
return hash;
}
}
当 运行 应用程序出现以下错误时:
Descriptor Exceptions:
---------------------------------------------------------
Exception [EclipseLink-48] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [ship_to.ship_to_id]. Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.OneToOneMapping[address]
Descriptor: RelationalDescriptor(model.ShipTo --> [DatabaseTable(ship_to)])
我的 ShipTo 实体需要与基于 ShipToPK.ship_to_id = Address.id
的地址建立一对一关系
同样,我的客户实体需要具有基于 CustomerPK.customerId = Address.id
的相同类型的关系
如有任何帮助,我们将不胜感激。谢谢,
您有两个使用 ship_to.ship_to_id 字段的映射,它们都是可写的。通常要使其工作,您需要决定要使用哪个映射来控制和设置该字段,并将另一个标记为 insertable=false、updatable=false。
虽然在这种情况下,该字段是一个 ID 字段,它也在您可能希望通过关系设置的外键映射中使用。这是一种常见的特殊情况,JPA 2.0 引入了派生 ID 支持,允许使用 @ID 注释标记关系。由于您使用的是 embeddableID,因此您还可以使用 @MapsId 注释,以便 JPA 使用引用实体的值设置 EmbeddedID 的 shipToId 属性。
类似于:
//bi-directional one-to-one association to Address
@OneToOne
@MapsId("shipToId")
@JoinColumn(name="ship_to_id", referencedColumnName="id")
private Address address;
JoinColumn 定义字段,@MapsId 强制它覆盖 shipToId 属性上的任何列定义。
注意:我是 JPA 开发的新手,正在学习 trial by fire,所以请原谅我可能遗漏的任何明显内容。
这是相关的 JPA 实体。地址未列出,但它是一个非常简单的实体,具有一个名为 id 的 @Id。
ShipTo.java
package model;
import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;
import java.sql.Timestamp;
/**
* The persistent class for the ship_to database table.
*
*/
@Entity
@Table(name="ship_to")
@NamedQuery(name="ShipTo.findAll", query="SELECT s FROM ShipTo s")
public class ShipTo implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private ShipToPK id;
//bi-directional many-to-one association to Customer
@ManyToOne
@JoinColumns({
@JoinColumn(name="company_id", referencedColumnName="company_id"),
@JoinColumn(name="customer_id", referencedColumnName="customer_id")
})
private Customer customer;
//bi-directional one-to-one association to Address
@OneToOne
@JoinColumn(name="ship_to_id", referencedColumnName="id")
private Address address;
ShipToPK.java
package model;
import java.io.Serializable;
import javax.persistence.*;
/**
* The primary key class for the ship_to database table.
*
*/
@Embeddable
public class ShipToPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(name="company_id", insertable=false, updatable=false)
private String companyId;
@Column(name="ship_to_id")
private long shipToId;
public ShipToPK() {
}
public String getCompanyId() {
return this.companyId;
}
public void setCompanyId(String companyId) {
this.companyId = companyId;
}
public long getShipToId() {
return this.shipToId;
}
public void setShipToId(long shipToId) {
this.shipToId = shipToId;
}
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof ShipToPK)) {
return false;
}
ShipToPK castOther = (ShipToPK)other;
return
this.companyId.equals(castOther.companyId)
&& (this.shipToId == castOther.shipToId);
}
public int hashCode() {
final int prime = 31;
int hash = 17;
hash = hash * prime + this.companyId.hashCode();
hash = hash * prime + ((int) (this.shipToId ^ (this.shipToId >>> 32)));
return hash;
}
}
当 运行 应用程序出现以下错误时:
Descriptor Exceptions:
---------------------------------------------------------
Exception [EclipseLink-48] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [ship_to.ship_to_id]. Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.OneToOneMapping[address]
Descriptor: RelationalDescriptor(model.ShipTo --> [DatabaseTable(ship_to)])
我的 ShipTo 实体需要与基于 ShipToPK.ship_to_id = Address.id
的地址建立一对一关系同样,我的客户实体需要具有基于 CustomerPK.customerId = Address.id
的相同类型的关系如有任何帮助,我们将不胜感激。谢谢,
您有两个使用 ship_to.ship_to_id 字段的映射,它们都是可写的。通常要使其工作,您需要决定要使用哪个映射来控制和设置该字段,并将另一个标记为 insertable=false、updatable=false。
虽然在这种情况下,该字段是一个 ID 字段,它也在您可能希望通过关系设置的外键映射中使用。这是一种常见的特殊情况,JPA 2.0 引入了派生 ID 支持,允许使用 @ID 注释标记关系。由于您使用的是 embeddableID,因此您还可以使用 @MapsId 注释,以便 JPA 使用引用实体的值设置 EmbeddedID 的 shipToId 属性。
类似于:
//bi-directional one-to-one association to Address
@OneToOne
@MapsId("shipToId")
@JoinColumn(name="ship_to_id", referencedColumnName="id")
private Address address;
JoinColumn 定义字段,@MapsId 强制它覆盖 shipToId 属性上的任何列定义。