当反向引用只是一个 id 属性而不是完整引用时,如何执行 OneToMany Hibernate 映射

发布于 2024-11-19 20:51:05 字数 1496 浏览 1 评论 0原文

让我更具体地说,很难在标题中描述这一点。

我有一个名为 Bucket 的类,它有一系列标签的映射。 Bucket 类有一个 id 属性。 Label 类没有对 Bucket 的引用,而是有一个 BucketId 字段,其中包含所属存储桶的 ID。这对于避免循环引用(Bucket 到 Label 以及返回 Label 到 Bucket)是必要的,以便允许 Bucket 对象转换为 JSON 表示法。

我的 Bucket 类如下所示:

@Entity(name="Bucket")
@Table(name = "BUCKETS")
public class Bucket implements Serializable {

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "BUCKET_ID")
    protected long id;

    /*
     * Map of labels indexed by the label name. I'm not sure this mapping is correct!
     */
    @ElementCollection
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @MapKeyColumn(name="LABEL_NAME")
    private Map<String, Label> labels = new HashMap<String, Label>();

    ...

}

Label 类如下所示:

@Entity(name="Label")
@Table(name = "LABELS")
public class Label implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "LABEL_ID")
    protected long id;

    /*
     * How do I map this? It should point to the id of the Bucket instance that has
     * this label in its "labels" map
     */
    protected long bucketId;


    @Column(name = "LABEL_NAME", length=250, nullable=false)
    private String name;

    ...

}

如果我可以在 Label 中包含 Bucket 引用,我会将其映射为 @OneToMany,然后在 Buckets 类中我将映射为 @ManyToOne(mappedBy=" Bucket”),但我没有那个引用,只有指向后面的 id。

有人知道我该如何映射它吗?

谢谢! 爱德华多

Let me be more specific, it was hard to describe this in the title.

I have a class called Bucket, which has a map to a series of Labels. The Bucket class has an id attribute. The class Label doesn't have a reference back to Bucket, instead it has a bucketId field which contains the id of the owning bucket. This was necessary to avoid circular references (Bucket to Label and back Label to Bucket) in order to allow the Bucket objects to be converted to JSON notation.

My Bucket class looks like this:

@Entity(name="Bucket")
@Table(name = "BUCKETS")
public class Bucket implements Serializable {

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "BUCKET_ID")
    protected long id;

    /*
     * Map of labels indexed by the label name. I'm not sure this mapping is correct!
     */
    @ElementCollection
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @MapKeyColumn(name="LABEL_NAME")
    private Map<String, Label> labels = new HashMap<String, Label>();

    ...

}

and the Label class looks like this:

@Entity(name="Label")
@Table(name = "LABELS")
public class Label implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "LABEL_ID")
    protected long id;

    /*
     * How do I map this? It should point to the id of the Bucket instance that has
     * this label in its "labels" map
     */
    protected long bucketId;


    @Column(name = "LABEL_NAME", length=250, nullable=false)
    private String name;

    ...

}

If I could have a Bucket reference in the Label, I would map it as a @OneToMany and then in the Buckets class I would map as @ManyToOne(mappedBy="bucket"), but I don't have that reference, just the id pointing back.

Does anyone knows how do I map this?

Thank you!
Eduardo

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

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

发布评论

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

评论(2

在巴黎塔顶看东京樱花 2024-11-26 20:51:05
@ElementCollection
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@MapKeyColumn(name="LABEL_NAME")
private Map<String, Label> labels = new HashMap<String, Label>();

首先,上面的映射不可能是正确的。使用 @ElementCollection 或 @OneToMany,但不能同时使用两者。

就 BuckedId 字段的映射而言,我只是将其映射为标签表中的普通 Long 字段。当您将标签添加到存储桶时,您可以使用正确的bucketId 初始化该字段。像这样(在 Bucket 类中):

public void addLabel(Label label) {
    labels.put(label.getName(), label);
    label.setBucketId(this.getId());
}

但是请确保 Labels 类中的 bucketId 字段不能设置为不正确的值。例如,您可以降低bucketId 字段的setter 的可见性。

@ElementCollection
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@MapKeyColumn(name="LABEL_NAME")
private Map<String, Label> labels = new HashMap<String, Label>();

First off the above mapping cannot be correct. Either use @ElementCollection OR @OneToMany, not both.

As far as the mapping of the buckedId field goes, i would just map it as a normal Long field in the Labels table. You could initialize the field with the correct bucketId, when you add a Label to a Bucket. Something like this (in the Bucket class):

public void addLabel(Label label) {
    labels.put(label.getName(), label);
    label.setBucketId(this.getId());
}

However make sure, the bucketId field in the Labels class cannot be set to an incorrect value. You could for example reduce the visibility of the setter for the bucketId field.

我的痛♀有谁懂 2024-11-26 20:51:05

由于某种原因,我无法在 GeorgeG 的回答下发表评论,所以我在这里回答你的第二个问题:

为了在创建存储桶后在标签中设置bucketId,你需要注册一个 EventListener 来执行以下操作例如,您想要(这不一定是工作代码)。

    public class LabelPostInsertListener implements PostInsertListener {

        public void onPostInsert(PostInsertEvent event)
                throws HibernateException {
            Bucket bucket = (Bucket)event.getEntity();
            for (Label l : bucket.getLabels().values()) {
                l.setBucketId(bucket.getId());
            }

        }
    }

Google Hibernate EventListeners 有关配置等详细信息,有许多不同的类型,尽管 PostInsertListener 应该适合这种情况。

For some reason I am not able to comment below GeorgeG's answer, so I am responding to your second question here:

In order to set the bucketId in the Label after the Bucket has been created, you'll need to register an EventListener to do what you want to, for example (this is not necessarily working code).

    public class LabelPostInsertListener implements PostInsertListener {

        public void onPostInsert(PostInsertEvent event)
                throws HibernateException {
            Bucket bucket = (Bucket)event.getEntity();
            for (Label l : bucket.getLabels().values()) {
                l.setBucketId(bucket.getId());
            }

        }
    }

Google Hibernate EventListeners for details on configuration and the like, there are many different types, though PostInsertListener should do be right for this situation.

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