Postgresql和Eclipselink的Netbeans代码-识别关系问题

Postgresql和Eclipselink的Netbeans代码-识别关系问题,postgresql,orm,netbeans,eclipselink,jpa-2.0,Postgresql,Orm,Netbeans,Eclipselink,Jpa 2.0,我有以下数据库表: 一方,其pk pty_id连接到用于生成pk值的序列。 与party.pty_id具有身份关系的fpk prs_pty_id的人员。 公司这目前还没有涉及,但显然这是一种子超类设置,它可能已经用postgresql中的子类化机制实现了,但这是另一天的事情。 因此,我使用Netbeans 6.9.1生成JPA实体类和控制器/dao代码来处理这个问题。它工作得很好,我只需要向Party实体bean添加一个注释:@GeneratedValuestrategy=GenerationT

我有以下数据库表:

一方,其pk pty_id连接到用于生成pk值的序列。 与party.pty_id具有身份关系的fpk prs_pty_id的人员。 公司这目前还没有涉及,但显然这是一种子超类设置,它可能已经用postgresql中的子类化机制实现了,但这是另一天的事情。 因此,我使用Netbeans 6.9.1生成JPA实体类和控制器/dao代码来处理这个问题。它工作得很好,我只需要向Party实体bean添加一个注释:@GeneratedValuestrategy=GenerationType.IDENTITY。Person实体bean不需要这样做,因为它应该始终具有它所连接的一方的pk值

所以我要做的就是创造一个人:

PartyJpaController parController = new PartyJpaController();
PersonJpaController perController = new PersonJpaController();
Party par = new Party();
Person per = new Person();
par.setComment("jalla");
per.setName("Per Vers");
parController.create(par);
per.setPrsPtyId(par.getPtyId()); // <== why do I need to set this ...
Long partyId = par.getPtyId();
par.setPerson(per); // <== ... when this explicitly expresses the relationship?
perController.create(per);
parController.edit(par);

Party foundParty = parController.findParty(partyId);

Person foundPerson = foundParty.getPerson();
System.err.println(foundPerson.getName());
在perController.createper中,它是由Netbeans生成的代码:

EntityManager em = null;
try {
    em = getEntityManager();
    em.getTransaction().begin();
    Party party = person.getParty();
    if (party != null) {
        party = em.getReference(party.getClass(), party.getPtyId()); // <== Exception thrown here
        person.setParty(party);
    }
    em.persist(person);
    if (party != null) {
        party.setPerson(person);
        party = em.merge(party);
    }
    em.getTransaction().commit();
所以,我想Netbeans生成的代码没有经过很好的调整来识别关系?最好的编码方式是什么

使用的软件:Eclipselink版本2.1.1 Postgresql 8.4 Netbeans 6.9.1 Java/JDK 1.6.021

这是我的bean,它们是由netbeans 6.9.1从模式生成的,除了参与方中的@GeneratedValuestrategy=GenerationType.IDENTITY,我添加它是为了在postgresql中使用串行/序列pk生成

/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.martinsolaas.webmarin.jpa; import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.MapsId; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; /** * * @author jms */ @Entity @Table(name = "person", catalog = "webmarin", schema = "webmarin") @NamedQueries({ @NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p"), @NamedQuery(name = "Person.findByPrsPtyId", query = "SELECT p FROM Person p WHERE p.prsPtyId = :prsPtyId"), @NamedQuery(name = "Person.findByName", query = "SELECT p FROM Person p WHERE p.name = :name"), @NamedQuery(name = "Person.findByCellphone", query = "SELECT p FROM Person p WHERE p.cellphone = :cellphone"), @NamedQuery(name = "Person.findByOfficephone", query = "SELECT p FROM Person p WHERE p.officephone = :officephone")}) public class Person implements Serializable { private static final long serialVersionUID = 1L; @Id @Basic(optional = false) @Column(name = "prs_pty_id", nullable = false) @MapsId private Long prsPtyId; @Column(name = "name", length = 255) private String name; @Column(name = "cellphone", length = 55) private String cellphone; @Column(name = "officephone", length = 55) private String officephone; @JoinColumn(name = "prs_pty_id", referencedColumnName = "pty_id", nullable = false, insertable = false, updatable = false) @OneToOne(optional = false) private Party party; public Person() { } public Person(Long prsPtyId) { this.prsPtyId = prsPtyId; } public Long getPrsPtyId() { return prsPtyId; } public void setPrsPtyId(Long prsPtyId) { this.prsPtyId = prsPtyId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCellphone() { return cellphone; } public void setCellphone(String cellphone) { this.cellphone = cellphone; } public String getOfficephone() { return officephone; } public void setOfficephone(String officephone) { this.officephone = officephone; } public Party getParty() { return party; } public void setParty(Party party) { this.party = party; } @Override public int hashCode() { int hash = 0; hash += (prsPtyId != null ? prsPtyId.hashCode() : 0); return hash; } @Override public boolean equals(Object object) { // TODO: Warning - this method won't work in the case the id fields are not set if (!(object instanceof Person)) { return false; } Person other = (Person) object; if ((this.prsPtyId == null && other.prsPtyId != null) || (this.prsPtyId != null && !this.prsPtyId.equals(other.prsPtyId))) { return false; } return true; } @Override public String toString() { return "com.martinsolaas.webmarin.jpa.Person[prsPtyId=" + prsPtyId + "]"; } } 最后,这里是SQL模式

CREATE SEQUENCE webmarin.party_pty_id_seq; CREATE TABLE webmarin.party ( pty_id BIGINT NOT NULL DEFAULT nextval('webmarin.party_pty_id_seq'), comment TEXT NOT NULL, CONSTRAINT pty_pk PRIMARY KEY (pty_id) ); ALTER SEQUENCE webmarin.party_pty_id_seq OWNED BY webmarin.party.pty_id; CREATE TABLE webmarin.company ( cmp_pty_id BIGINT NOT NULL, name VARCHAR(255) NOT NULL, CONSTRAINT cmp_pk PRIMARY KEY (cmp_pty_id) ); CREATE TABLE webmarin.party_relationship ( parent_pty_id BIGINT NOT NULL, child_pty_id BIGINT NOT NULL, CONSTRAINT ptr_pk PRIMARY KEY (parent_pty_id, child_pty_id) ); CREATE TABLE webmarin.person ( prs_pty_id BIGINT NOT NULL, name VARCHAR(255), cellphone VARCHAR(55), officephone VARCHAR(55), CONSTRAINT prs_pk PRIMARY KEY (prs_pty_id) ); ALTER TABLE webmarin.party_relationship ADD CONSTRAINT parent_party_party_relationship_fk FOREIGN KEY (parent_pty_id) REFERENCES webmarin.party (pty_id) ON DELETE NO ACTION ON UPDATE NO ACTION NOT DEFERRABLE; ALTER TABLE webmarin.party_relationship ADD CONSTRAINT child_party_party_relationship_fk FOREIGN KEY (child_pty_id) REFERENCES webmarin.party (pty_id) ON DELETE NO ACTION ON UPDATE NO ACTION NOT DEFERRABLE; ALTER TABLE webmarin.person ADD CONSTRAINT party_person_fk FOREIGN KEY (prs_pty_id) REFERENCES webmarin.party (pty_id) ON DELETE NO ACTION ON UPDATE NO ACTION NOT DEFERRABLE; ALTER TABLE webmarin.company ADD CONSTRAINT party_company_fk FOREIGN KEY (cmp_pty_id) REFERENCES webmarin.party (pty_id) ON DELETE NO ACTION ON UPDATE NO ACTION NOT DEFERRABLE;
JPA2.0极大地改进了对带有Id和MapsId注释的派生标识符的支持,现在您可以在XxxToOne关联上使用它们,它们应该是首选。以下是本规范中的一个示例:

2.4.1.3衍生恒等式示例

例4:

父实体有一个简单的主实体 关键:

案例a:依赖实体有一个主键属性 由关系映射 属性的主键 MedicalHistory的类型为String

示例查询:

SELECT m
FROM MedicalHistory m
WHERE m.patient.ssn = '123-45-6789'
SELECT m
FROM MedicalHistory m WHERE m.patient.ssn = '123-45-6789'
案例b:依赖实体具有单个主键属性 对应关系 属性主键属性 其基本类型与 父实体的主键。这个 应用于 关系属性表示 主键由 关系属性

@Entity
public class MedicalHistory {
    @Id String id; // overriding not allowed
    ...
    // default join column name is overridden
    @MapsId
    @JoinColumn(name="FK")
    @OneToOne Person patient;
    ...
}
示例查询:

SELECT m
FROM MedicalHistory m
WHERE m.patient.ssn = '123-45-6789'
SELECT m
FROM MedicalHistory m WHERE m.patient.ssn = '123-45-6789'
我想MapsId可能就是你要找的

后续行动:与此相反:

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "prs_pty_id", nullable = false)
    @MapsId
    private Long prsPtyId;
    @Column(name = "name", length = 255)
    private String name;
    @Column(name = "cellphone", length = 55)
    private String cellphone;
    @Column(name = "officephone", length = 55)
    private String officephone;
    @JoinColumn(name = "prs_pty_id", referencedColumnName = "pty_id", nullable = false, insertable = false, updatable = false)
    @OneToOne(optional = false)
    private Party party;
    ...
}
试试这个:

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "prs_pty_id", nullable = false)
    private Long prsPtyId;
    @Column(name = "name", length = 255)
    private String name;
    @Column(name = "cellphone", length = 55)
    private String cellphone;
    @Column(name = "officephone", length = 55)
    private String officephone;
    @MapsId
    @JoinColumn(name = "prs_pty_id", referencedColumnName = "pty_id")
    @OneToOne
    private Party party;
    ...
}
工具书类 JPA2.0规范 第2.4.1节与派生标识对应的主键 第2.4.1.1节派生身份的规范 第2.4.1.2节派生身份的映射 第2.4.1.3节衍生恒等式示例 JPA维基百科
很抱歉,它没有按预期工作,Eclipse链接仍然尝试创建一个pk为空的person行。示例代码:em.getTransaction.begin;政党=新党;每人=新的人;好的;per.setNamePer-Vers;设定人;em.par;em.getTransaction.commit;Hibernate也不行。@user275886请编辑您的问题以显示您的实体和映射。映射是问题所在,而不是用于持久化的代码,因此如果不显示它们,我什么也说不出来。我会尽快这样做,直到那时,实体基本上与netbeans生成它们一样,我不使用任何特殊映射。我现在为模式添加了bean源代码和DDL,我没有任何特定的映射配置,只有一个极小的persistence.xml将eclipselink声明为提供者、连接数据等。感谢您的关注:-好的,我想,现在我得到了异常描述:应该为主键字段[webmarin.webmarin.person.prs_pty_id]定义一个非只读映射。看来我需要一个映射,但是如何,在哪里,以及?
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "prs_pty_id", nullable = false)
    @MapsId
    private Long prsPtyId;
    @Column(name = "name", length = 255)
    private String name;
    @Column(name = "cellphone", length = 55)
    private String cellphone;
    @Column(name = "officephone", length = 55)
    private String officephone;
    @JoinColumn(name = "prs_pty_id", referencedColumnName = "pty_id", nullable = false, insertable = false, updatable = false)
    @OneToOne(optional = false)
    private Party party;
    ...
}
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "prs_pty_id", nullable = false)
    private Long prsPtyId;
    @Column(name = "name", length = 255)
    private String name;
    @Column(name = "cellphone", length = 55)
    private String cellphone;
    @Column(name = "officephone", length = 55)
    private String officephone;
    @MapsId
    @JoinColumn(name = "prs_pty_id", referencedColumnName = "pty_id")
    @OneToOne
    private Party party;
    ...
}