2009-07-08 68 views
4

我的数据库有两个实体;公司和个人。一个公司可以有很多人,但一个人只能有一个公司。表结构如下所示。使用Eclipselink/JPA,我可以使用与主复合键共享字段的外来复合键吗?

COMPANY 
---------- 
owner PK 
comp_id PK 
c_name
PERSON 
---------------- 
owner PK, FK1 
personid PK 
comp_id FK1 
p_fname 
p_sname

它发生,我认为我可以删除PERSON.OWNER并通过外键得到它;但是,我不能在不影响遗留代码的情况下进行此更改。

我将这些建模为JPA注释类;

@Entity 
@Table(name = "PERSON") 
@IdClass(PersonPK.class) 
public class Person 
    implements Serializable { 

    @Id 
    private String owner; 

    @Id 
    private String personid; 

    @ManyToOne 
    @JoinColumns(
    {@JoinColumn(name = "owner", referencedColumnName = "OWNER", 
       insertable = false, updatable = false), 
    @JoinColumn(name = "comp_id", referencedColumnName = "COMP_ID", 
       insertable = true, updatable = true)}) 
    private Company company; 

    private String p_fname; 

    private String p_sname; 

    ...and standard getters/setters... 
}
@Entity 
@Table(name = "COMPANY") 
@IdClass(CompanyPK.class) 
public class Company 
    implements Serializable { 

    @Id 
    private String owner; 

    @Id 
    private String comp_id; 

    private String c_name; 

    @OneToMany(mappedBy = "company", cascade=CascadeType.ALL) 
    private List people; 

    ...and standard getters/setters... 
}

我PersonPK和CompanyPK类是没有什么特别的,他们只是作为一个结构持有所有者和ID字段,并重写了hashCode和equals(O)。

到目前为止这么好。然而,当我试图对付社团时,我遇到了一个问题。看起来,如果我拥有一个现有公司并创建一个人,并将该人员关联到该公司并坚持该公司,则该人员插入时该关联不会被保存。例如,我的主代码如下所示:

EntityManager em = emf.createEntityManager(); 
em.getTransaction().begin(); 

CompanyPK companyPK = new CompanyPK(); 
companyPK.owner="USA"; 
companyPK.comp_id="1102F3"; 
Company company = em.find(Company.class, companyPK); 

Person person = new Person(); 
person.setOwner("USA"); 
person.setPersonid("5116628123"); //some number that doesn't exist yet 
person.setP_fname("Hannah"); 
person.setP_sname("Montana"); 
person.setCompany(company); 
em.persist(person);

完成时没有错误;但是在数据库中,我发现Person记录在COMP_ID字段中插入了一个空值。随着EclipseLink的调试日志记录设置为FINE,SQL查询显示为:

INSERT INTO PERSON (PERSONID,OWNER,P_SNAME,P_FNAME) VALUES (?,?,?,?) 
    bind => [5116628123,USA,Montana,Hannah,]

我本来期望这是保存,查询等同于

INSERT INTO PERSON (PERSONID,OWNER,COMP_ID,P_SNAME,P_FNAME) VALUES (?,?,?,?,?) 
    bind => [5116628123,USA,1102F3,Montana,Hannah,]

是怎么回事?对于组合键的一半说updatable/insertable = true,另一半是false =是不正确的?如果我的外键的两个部分都有updatable/insertable = true,那么Eclipselink无法启动,说我不能通过指定这些选项来使用列两次,而没有一次设置为只读。

回答

1

我有同样的问题。我发现的解决方案是将主键字段设置为不可插入和不可更新。你的个人实体应该是这样的:

@Entity 
@Table(name = "PERSON") 
@IdClass(PersonPK.class) 
public class Person 
    implements Serializable { 

    @Id 
    @Column(insertable = false, updatable=false) 
    private String owner; 

    @Id 
    private String personid; 

    @Id 
    @Column(insertable = false, updatable=false) 
    private String comp_id; 


    @ManyToOne 
    @JoinColumns({ 
    @JoinColumn(name = "owner", referencedColumnName = "OWNER"), 
    @JoinColumn(name = "comp_id", referencedColumnName = "COMP_ID") 
    }) 
    private Company company; 

    private String p_fname; 

    private String p_sname; 

    ...and standard getters/setters... 
} 
+0

你能否详细说明?这样做的效果是什么? (比方说)所有者属性在什么阶段被赋值? – djna 2011-07-08 07:19:43

0

我这样做的方法是标注在PK类中的字段一样,如果他们是在实体上我会。

然后在实体中没有PK类所拥有的字段。如果你愿意,你可以实现吸气剂是直通

class Person { 
    ..... 

private PersonPK pk; 

@Id 
public PersonPK getPk() { return pk; } 

@Transient 
public String getOwner() { 
    return pk.getOwner(); 
} 
.... 
} 

的PersonPK需要可序列化和annoted @Embeddable

@Embeddable 
class PersonPK implements Serializable { 
4

您的代码应该工作。确保你重新编译/正确部署它。 你使用的是什么版本?

还要确保您的公司对象具有有效的ID集。

你也可以尝试把,

insertable = false, updatable = false 
在所有者字段的@Column

,离开整个外键插入/更新。

0

除了数据库的设计是相当怪异,这可能工作:

@Entity 
public class Company 
{ 
    @EmbeddedId 
    private CompanyPK key; 

    @MapsId(value = "ownerId") 
    @OneToMany 
    @JoinColumn(name = "owner", referencedColumnName = "personid") 
    private Person owner; 

    @ManyToOne(mappedBy = "company") 
    private List<Person> persons; 

    @Column(name = "c_name") 
    private String name; 
} 

@Embeddable 
public class CompanyPK 
{ 
    @Column(name = "comp_id") 
    private String id; 

    @Column(name = "owner") 
    private String ownerId; 
} 

@Entity 
public class Person 
{ 
    @EmbeddedId 
    private PersonPK key; 

    @MapdId(value = "ownerId") 
    private Person owner; 

    @ManyToOne 
    @JoinColumns({ 
     @JoinColumn(name = "owner", referencedColumnName = "owner") 
     @JoinColumn(name = "comp_id", referencedColumnName = "comp_id") 
    }) 
    private Company company; 

    @Column(name = "p_fname") 
    private String firstName; 

    @Column(name = "p_sname") 
    private String surName; 
} 

@Embeddable 
public class PersonPK 
{ 
    @Column(name = "personid") 
    private String id; 

    @Column(name = "owner") 
    private String ownerId; 
}