简体   繁体   English

与@JoinColumn和@MapKeyColumn保持@OneToMany关系

[英]Persisting @OneToMany relations with @JoinColumn and @MapKeyColumn

I have two entities: 我有两个实体:

@Entity
Article {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
    @JoinColumn(name="embed_id", referencedColumnName="id")
    @MapKeyColumn(name = "language")
    @MapKeyEnumerated(EnumType.ORDINAL)
    private Map<Language, Locale> locales;

    Article() {
        locales.put(Language.CS, new Locale());
        locales.put(Language.EN, new Locale());
    }
}

@Entity
Locale {
    @Id
    private Long embed_id;

    @Id
    private Language language;

    @Column(length = 256)
    private String name;
}

Thanks to the constructor, I can make sure, that once an Article is instantiated, two Locales (with CascadeType.ALL) are associated with it. 感谢构造函数,我可以确保,一旦实例化了一个Article就会将两个Locales (与CascadeType.ALL)相关联。

The problem comes when I try to persist such entity - I am getting: 当我试图坚持这样的实体时,问题出现了 - 我得到了:

javax.persistence.EntityExistsException: 
a different object with the same identifier value was already associated 
      with the session: org...Locale#org...Locale@2bfdsc64

The problem is that neither embed_id , nor language have assigned values from the Article when persisting and Hibernate does not associate them after persisting Article. 问题是embed_idlanguage都没有在持久化时从文章中赋值,而Hibernate在持久化文章后没有关联它们。 How can this be done? 如何才能做到这一点?

Edit 1: 编辑1:

I checked that when the embed_id and language are set manually, everything works correctly. 我检查过,当手动设置embed_idlanguage ,一切正常。 I just need to tell Hibernate, to set the value of @ JoinColumn and @ MapKeyColumn according to the @ OneToMany relation. 我只需要告诉Hibernate,根据@ OneToMany关系设置@ JoinColumnMapKeyColumn的值。

Edit 2: 编辑2:

The problem with MapKeyColumn has an easy solution: MapKeyColumn的问题有一个简单的解决方案:

 public void addLocale(Language l, Locale locale) {
      locale.setLanguage(l);
      this.locales.put(l);
 }

But I am still unable to tell hibernate to associate the Locale.embed_id from Article.id. 但我仍然无法告诉hibernate将Article.id与Locale.embed_id相关联。

Edit 3: 编辑3:

I can see that the ID of article is properly generated, but then it is not put in the locale: 我可以看到文章的ID是正确生成的,但是它没有放在语言环境中:

DEBUG org.hibernate.event.internal.AbstractSaveEventListener - 
    Generated identifier: 87, using strategy: org.hibernate.id.SequenceGenerator
DEBUG org.hibernate.event.internal.AbstractSaveEventListener - 
    Generated identifier: component[language,embedId]{language=0, embedId=null}, using strategy: org.hibernate.id.CompositeNestedGeneratedValueGenerator
DEBUG org.hibernate.event.internal.AbstractSaveEventListener - 
    Generated identifier: component[language,embedId]{language=1, embedId=null}, using strategy: org.hibernate.id.CompositeNestedGeneratedValueGenerator

I guess the problem is, that you want to persist two empty locales. 我想问题是,你想要坚持两个空的语言环境。 And because you don't use a generator for the id-fields, the locales have the same (empty) primary key and therefore can't be persisted. 并且因为您没有为id字段使用生成器,所以语言环境具有相同的(空)主键,因此无法持久化。

I finally found the anwswer! 我终于找到了anwswer! The trick was to create Setter on Article and add Access to id as follows: 诀窍是在文章上创建Setter并添加对id的访问,如下所示:

@Id
@Getter
@Access(AccessType.PROPERTY)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

public void setId(Long id) {
    this.id = id;
    this.getLocale(Language.CS).setEmbedId(id);
    this.getLocale(Language.EN).setEmbedId(id);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM