使用hibernate中的共享外键列映射两个实体

时间:2010-09-20 21:43:58

标签: java hibernate hibernate-annotations

我有四个实体一起映射,“关联”,“帐户”,“交易”和“交易事件”。 Association的id是一个简单的整数id。账户和交易每个都有嵌入的ID,包括到关联和数字的映射。

TransactionEvent应具有由一个帐户和一个关联组成的嵌入式ID。现在,每个都映射到一个Association,我希望它是一个TransactionEvent的同一个Association。

JPA Annotations用于Hibernate映射,但我无法使其工作。我已经尝试为Association键强制使用相同的列名,但是Hibernate抱怨重复的列。

这有可能解决,还是我不直接思考?

以下是带注释的类,但我从javax.persistence命名空间中删除了getter / setter和non-id列,注释:


@Entity
public class Association implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
}

@Embeddable
public class AccountPK implements Serializable {
    @ManyToOne(optional=false)
    private Association association;

    @Column(nullable=false)
    private int number;
}

@Embeddable
public class TransactionPK implements Serializable {
    @ManyToOne
    private Association association;

    @GeneratedValue(strategy=GenerationType.AUTO)
    private long number;
}

@Embeddable
public class AccountEventPK implements Serializable {
    @ManyToOne(optional=false)
    @JoinColumns({
        @JoinColumn(name="association_id", referencedColumnName="association_id"),
        @JoinColumn(name="account_number", referencedColumnName="number")
    })
    private Account account;

    @ManyToOne(optional=false)
    @JoinColumns({
        @JoinColumn(name="association_id", referencedColumnName="association_id"),
        @JoinColumn(name="transaction_number", referencedColumnName="number")
    })
    private Transaction transaction;
}

实际帐户,交易和AccountEvent实体位于表单


@Entity
public class Account implements Serializable {
        @EmbeddedId
        private AccountPK id;
}

1 个答案:

答案 0 :(得分:2)

我没有太多将关联直接放在嵌入式id组件中的经验,因为JPA不支持这种关联,但是Hibernate是特定的。

作为替代方案,我的建议是使用JPA wikibook的Composite Primary Keys部分中描述的方法:

  

(...)JPA 1.0要求所有@Id   映射是Basic映射,所以如果   您的Id来自外键   通过OneToOne或。列   ManyToOne映射,您还必须   定义一个基本的@Id映射   外键栏目。的原因   这部分是Id必须是a   身份和缓存的简单对象   用途,并用于IdClass   或EntityManager find() API。

     

因为您现在有两个映射   你必须使用相同的外键列   定义将写入哪一个   数据库(必须是基础   一),所以OneToOneManyToOne   必须定义外键   只读。这是通过完成的   设置JoinColumn属性   insertableupdatable为假,   或者使用   @PrimaryKeyJoinColumn代替   @JoinColumn

     

具有两个映射的副作用   对于同一列,就是你现在   必须保持两者同步。这是   通常通过设置完成   OneToOne属性的方法   还将Basic属性值设置为   目标对象的id。这个可以   如果目标变得非常复杂   对象的主键是a   GeneratedValue,在这种情况下你   必须确保目标对象的   id已在相关之前分配   这两个对象。

     

(...)

     

示例ManyToOne ID注释

...
@Entity
@IdClass(PhonePK.class)
public class Phone {
    @Id
    @Column(name="OWNER_ID")
    private long ownerId;

    @Id
    private String type;

    @ManyToOne
    @PrimaryKeyJoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
    private Employee owner;
    ...

    public void setOwner(Employee owner) {
        this.owner = owner;
        this.ownerId = owner.getId();
    }
    ...
}

这看起来像是你正在寻找的东西(也许不那么复杂)。我试着逐步实现这个解决方案。