0

我有四个实体要映射在一起,“Association”、“Account”、“Transaction”和“TransactionEvent”。Association 的 id 是一个简单的整数 id。Account 和 Transaction 每个都有嵌入的 id,由一个到 Association 的映射和一个数字组成。

TransactionEvent 应该有一个嵌入的 id,由一个 Account 和一个 Association 组成。现在,它们中的每一个都映射到一个关联,我希望它与一个 TransactionEvent 的关联相同。

JPA Annotations 用于 Hibernate 映射,但我无法完成这项工作。我尝试为关联键强制使用相同的列名,但 Hibernate 抱怨重复的列。

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

这是带注释的类,但我从 javax.persistence 命名空间中删除了 getter/setter 和非 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;
}

实际的 Account、Transaction 和 AccountEvent 实体在表单上


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

1 回答 1

2

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

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

(...) JPA 1.0 要求所有@Id 映射都是映射,因此如果您的 Id 通过 a or 映射Basic来自外键列,您还必须为外键列定义基本 @Id 映射。部分原因是 Id 必须是用于身份和缓存目的的简单对象,以及用于API 或API。OneToOneManyToOneIdClassEntityManager find()

因为您现在对同一个外键列有两个映射,您必须定义哪一个将写入数据库(它必须是基本的),所以OneToOneorManyToOne 外键必须定义为只读的。这是通过将JoinColumn属性 insertable和设置updatable为 false 或使用 @PrimaryKeyJoinColumn代替 来完成的 @JoinColumn

对同一列有两个映射的副作用是您现在必须使两者保持同步。这通常通过让OneToOne属性的 set 方法也将 Basic 属性值设置为目标对象的 id 来完成。如果目标对象的主键是 a ,这会变得非常复杂 GeneratedValue,在这种情况下,您必须确保在关联两个对象之前已经分配了目标对象的 id。

(...)

示例ManyToOneid 注释

...
@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();
    }
    ...
}

这看起来就是您正在寻找的东西(并且可能不那么复杂)。我会尝试实施这个解决方案(增量)。

于 2010-09-21T22:37:24.773 回答