java - JPA 将具有 PK 的实体映射到具有复合 PK 的实体

标签 java jpa eclipselink

注意:我是 JPA 开发的新手,正在快速学习试用,所以请原谅我可能遗漏的任何明显内容。

以下是相关的 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 的 Address 建立一对一关系

同样,我的客户实体需要具有基于 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 属性上的任何列定义。

关于java - JPA 将具有 PK 的实体映射到具有复合 PK 的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35163072/

相关文章:

java - Struts2 当索引是变量时访问列表的特定索引

java - Android MediaPlayer 已定稿但未发布

java - org.hibernate.hql.internal.ast.QuerySyntaxException : Product is not mapped

java - 如何将 javax.persistence.Column 定义为 Unsigned TINYINT?

jpa - 函数式运算符导致 JPA 崩溃? (漏洞?)

java - 从另一个子类对象创建子类对象

java - 如何在 Android 中明确禁用 HTTP 连接的分块流模式?

java - 为什么分离实体被视为 transient ?

java - JPA @ManyToOne 连接表问题

java - JPA 如何获取 Criteria API 中使用的参数标记的数量?