Postgresql和Eclipselink的Netbeans代码-识别关系问题
我有以下数据库表: 一方,其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值 所以我要做的就是创造一个人: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
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;
...
}