5

我的数据库有两个实体;公司和个人。一个公司可以有很多人,但一个人必须只有一个公司。表结构如下所示。

公司
----------
业主PK
comp_id PK
c_name
人
----------------
所有者PK,FK1
人物PK
comp_id FK1
p_fname
p_sname

我突然想到我可以删除 PERSON.OWNER 并通过外键派生它;但是,我无法在不影响遗留代码的情况下进行此更改。

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

@实体
@Table(name = "PERSON")
@IdClass(PersonPK.class)
公共类人
    实现可序列化{

  @ID
  私有字符串所有者;

  @ID
  私人字符串personid;

  @ManyToOne
  @JoinColumns(
    {@JoinColumn(name = "owner", referencedColumnName = "OWNER",
                 可插入 = 假,可更新 = 假),
     @JoinColumn(name = "comp_id", referencedColumnName = "COMP_ID",
                 可插入=真,可更新=真)})
  私人公司公司;

  私有字符串 p_fname;

  私人字符串 p_sname;

  ...和标准的 getter/setter ...
}
@实体
@Table(名称 = "公司")
@IdClass(CompanyPK.class)
公共类公司
    实现可序列化{

  @ID
  私有字符串所有者;

  @ID
  私人字符串comp_id;

  私有字符串 c_name;

  @OneToMany(mappedBy = "公司", cascade=CascadeType.ALL)
  私人名单人;

  ...和标准的 getter/setter ...
}

我的 PersonPK 和 CompanyPK 类没有什么特别之处,它们只是作为一个结构体持有所有者和 ID 字段,并覆盖 hashCode 和 equals(o)。

到目前为止,一切都很好。但是,在尝试处理关联时,我遇到了一个问题。似乎如果我有一个现有的公司,并创建一个人,并将该人关联到该公司并坚持该公司,则插入该人时该关联不会被保存。例如,我的主要代码如下所示:

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

CompanyPK companyPK = new CompanyPK();
companyPK.owner="美国";
companyPK.comp_id="1102F3";
公司公司 = em.find(Company.class, companyPK);

人人 = 新人();
person.setOwner("美国");
person.setPersonid("5116628123"); //一些不存在的数字
person.setP_fname("汉娜");
person.setP_sname("蒙大拿州");
人.setCompany(公司);
em.persist(人);

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

插入人(PERSONID,OWNER,P_SNAME,P_FNAME)值(?,?,?,?)
  绑定 => [5116628123,美国,蒙大拿州,汉娜,]

我本来希望这会被保存,并且查询相当于

插入人(PERSONID,OWNER,COMP_ID,P_SNAME,P_FNAME)值(?,?,?,?,?)
  绑定 => [5116628123,美国,1102F3,蒙大拿州,汉娜,]

是什么赋予了?对组合键的一半说可更新/可插入=true 对另一半说 =false 是否不正确?如果我对外键的两个部分都有可更新/可插入=真,那么 Eclipselink 无法启动,说如果没有通过指定这些选项将一个设置为只读,我不能使用该列两次。

4

4 回答 4

4

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

还要确保您的 Company 对象具有有效的 id 集。

你也可以尝试把 ,

insertable = false, updatable = false

在您的所有者字段的 @Column 中,并使整个外键可插入/可更新。

于 2012-04-26T13:44:26.220 回答
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...
}
于 2009-08-05T08:56:37.663 回答
0

我这样做的方法是注释 PK 类中的字段,就像我在实体上一样。

然后在实体中没有 PK 类拥有的字段。如果你愿意,你可以实现传递的getter

class Person {
  .....

private PersonPK pk;

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

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

PersonPK 需要可序列化和注释@Embeddable

@Embeddable
class PersonPK implements Serializable {
于 2009-08-05T12:33:14.140 回答
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;
}
于 2012-06-08T00:14:43.573 回答