Сохранение отношений @OneToMany с @JoinColumn и @MapKeyColumn - PullRequest
4 голосов
/ 31 марта 2012

У меня есть две сущности:

@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_id, ни language не присвоили значения из статьипри сохранении и Hibernate не связывает их после сохранения статьи.Как это можно сделать?

Редактировать 1:

Я проверил, что когда embed_id и language установлены вручную, все работает правильно.Мне просто нужно сказать Hibernate, чтобы установить значения @ JoinColumn и @ MapKeyColumn в соответствии с отношением @ OneToMany.

Редактировать 2:

Проблема с MapKeyColumn имеет простое решение:

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

Но я все еще не могу сказать hibernate для связывания Locale.embed_id из Article.id.

Редактировать 3:

Я вижу, что идентификатор статьи генерируется правильно, но затем он не помещается в локаль:

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 ]

3 голосов
/ 31 марта 2012

Думаю, проблема в том, что вы хотите сохранить две пустые локали.А поскольку вы не используете генератор для полей id, локали имеют одинаковый (пустой) первичный ключ и поэтому не могут быть сохранены.

0 голосов
/ 03 апреля 2012

Я наконец нашел ответ! Хитрость заключалась в том, чтобы создать Setter on Article и добавить Access to 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...