2012-03-31 2 views
4

У меня есть две сущности:сохраняющиеся @OneToMany отношения с @JoinColumn и @MapKeyColumn

@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#[email protected] 

Проблема заключается в том, что ни embed_id, ни language присвоены значения из статьи, когда сохраняющиеся и Hibernate не связывает их после того, как сохраняющаяся статья. Как это может быть сделано?

Edit 1:

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

Edit 2:

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

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

Но я до сих пор не могу сказать спящий режим, чтобы связать Locale.embed_id из Article.id.

Edit 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 

ответ

0

Я наконец нашел ответный вопрос! Хитрость заключалась в создании 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); 
} 
3

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

+0

Я знаю, но как я могу сказать, что спящий режим связывает их с ключом Карты? Это не только язык, потому что, когда я устанавливаю его вручную, я получаю: «значение null в столбце« embed_id »нарушает не-нулевое ограничение;' –

+0

Но 'embed_id' не обязательно уникален (потому что вы объединяете его с' language' для достижения уникальности). Вероятно, не уникальный ключ не может быть (уникальным) ключом «карты»? –

+0

Уникально сочетается с языком. Первичным ключом является комбинация «embed_id, language». –

Смежные вопросы