在休眠中使用共享外键列映射两个实体

发布于 2024-09-24 09:19:25 字数 1756 浏览 6 评论 0原文

我有四个实体要映射在一起:“关联”、“帐户”、“交易”和“交易事件”。 Association的id是一个简单的整数id。帐户和交易均嵌入了由关联映射和数字组成的 ID。

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

JPA 注释用于 Hibernate 映射,但我无法使其工作。我尝试强制关联键使用相同的列名称,但 Hibernate 抱怨重复的列。

这个问题可以解决吗,还是我思路不清晰?

以下是带注释的类,但我删除了 getter/setter 和非 id 列以及来自 javax.persistence 命名空间的注释:


@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;
}

I have four entities to map together, "Association", "Account", "Transaction" and "TransactionEvent". The id of Association is a simple integer id. Account and Transaction each have embedded id's consisting of a mapping to an Association and a number.

TransactionEvent should have an embedded id consisting of one Account and one Association. Now, each of those are mapped to an Association, and I want it to be the same Association for one TransactionEvent.

JPA Annotations is used for the Hibernate mapping, but I cannot make this work. I have tried forcing the same column name for the Association key, but Hibernate complains about repeated columns.

Is this possible to solve, or am I not thinking straight?

Here are the annotated classes, but I trimmed away getters/setters and non-id columns, annotations from the javax.persistence namespace:


@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;
}

Actual Account, Transaction and AccountEvent entities are on the form


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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

<逆流佳人身旁 2024-10-01 09:19:25

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

作为替代方案,我的建议是使用复合主键 JPA wikibook 的部分:

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

因为您现在有两个映射
您必须使用相同的外键列
定义将写入哪一个
数据库(必须是Basic
一),因此 OneToOneManyToOne
外键必须定义为
只读。这是通过
设置 JoinColumn 属性
insertableupdatable 为 false,
或通过使用
@PrimaryKeyJoinColumn 而不是
@JoinColumn

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

(...)

ManyToOne id 注释示例

<前><代码>...
@实体
@IdClass(PhonePK.class)
公开课电话{
@ID
@Column(名称=“OWNER_ID”)
私有长所有者ID;

@ID
私有字符串类型;

@ManyToOne
@PrimaryKeyJoinColumn(名称=“OWNER_ID”,referencedColumnName=“EMP_ID”)
私人雇员所有者;
...

公共无效setOwner(员工所有者){
this.owner = 所有者;
this.ownerId = 所有者.getId();
}
...
}

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

I don't have much experience with placing associations directly in the embedded id component since this is not supported by JPA but is Hibernate specific.

As an alternative my suggestion would be to use the approach described in the Composite Primary Keys section of the JPA wikibook:

(...) JPA 1.0 requires that all @Id
mappings be Basic mappings, so if
your Id comes from a foreign key
column through a OneToOne or
ManyToOne mapping, you must also
define a Basic @Id mapping for the
foreign key column. The reason for
this is in part that the Id must be a
simple object for identity and caching
purposes, and for use in the IdClass
or the EntityManager find() API.

Because you now have two mappings for
the same foreign key column you must
define which one will be written to
the database (it must be the Basic
one), so the OneToOne or ManyToOne
foreign key must be defined to be
read-only. This is done through
setting the JoinColumn attributes
insertable and updatable to false,
or by using the
@PrimaryKeyJoinColumn instead of the
@JoinColumn.

A side effect of having two mappings
for the same column is that you now
have to keep the two in synch. This is
typically done through having the set
method for the OneToOne attribute
also set the Basic attribute value to
the target object's id. This can
become very complicated if the target
object's primary key is a
GeneratedValue, in this case you
must ensure that the target object's
id has been assigned before relating
the two objects.

(...)

Example ManyToOne id annotation

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

This looks like to be what you're looking for (and maybe less complicated). I'd try to implement this solution (incrementally).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文