有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我有两个实体:

@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关系设置JoinColumnMapKeyColumn的值

编辑2:

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

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

但我仍然无法告诉hibernate关联区域设置。从文章中嵌入\u 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

共 (2) 个答案

  1. # 1 楼答案

    我终于找到了答案!诀窍是在文章上创建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);
    }
    
  2. # 2 楼答案

    我想问题是,您希望保留两个空的区域设置。而且,由于没有为id字段使用生成器,因此区域设置具有相同的(空)主键,因此无法持久化