【问题标题】:Persisting @OneToMany relations with @JoinColumn and @MapKeyColumn与 @JoinColumn 和 @MapKeyColumn 保持 @OneToMany 关系
【发布时间】:2012-04-14 19:27:09
【问题描述】:

我有两个实体:

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

感谢构造函数,我可以确保,一旦实例化 Article,就会有两个 Locales(带有 CascadeType.ALL)与之关联。

当我试图坚持这样的实体时,问题就来了——我得到了:

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

问题是embed_idlanguage在持久化时都没有从文章中赋值,并且Hibernate在持久化文章后不会关联它们。如何做到这一点?

编辑 1:

我检查了当手动设置embed_idlanguage 时,一切正常。我只需要告诉Hibernate,根据@OneToMany关系设置@JoinColumn和@MapKeyColumn的值。

编辑 2:

MapKeyColumn 的问题有一个简单的解决方案:

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

但我仍然无法告诉 hibernate 将 Locale.embed_id 与 Article.id 相关联。

编辑 3:

我可以看到文章的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

【问题讨论】:

    标签: java hibernate jpa persistence


    【解决方案1】:

    我想问题是,你想保留两个空的语言环境。而且由于您没有为 id 字段使用生成器,因此语言环境具有相同的(空)主键,因此无法持久化。

    【讨论】:

    • 我知道,但是我如何告诉 hibernate 将它们与 Map 的键相关联?它不仅仅是语言 - 因为当我手动设置它时,我得到:null value in column "embed_id" violates not-null constraint;
    • 但是embed_id不一定是唯一的(因为你把它和language结合起来才能达到唯一性)。可能非唯一键不能是map 的(唯一)键?
    • 与语言相结合的独特之处。主键是embed_id,language 组合。
    • 我只需要了解如何告诉 HIbernate 更新这些字段。
    • 是的,我的意思是,只有组合是唯一的,而不是单独的embed_id,也许embed_id 不能成为map 的键,因为它不是唯一的。你知道我的意思吗?
    【解决方案2】:

    我终于找到答案了!诀窍是在 Article 上创建 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-20
      • 2021-12-27
      • 1970-01-01
      • 2014-12-01
      相关资源
      最近更新 更多