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.
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. How can this be done?
Edit 1:
I checked that when the embed_id and language are set manually, everything works correctly. I just need to tell Hibernate, to set the value of @JoinColumn and @MapKeyColumn according to the @OneToMany relation.
Edit 2:
The problem with MapKeyColumn has an easy solution:
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.
Edit 3:
I can see that the ID of article is properly generated, but then it is not put in the locale:
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 finally found the anwswer! The trick was to create Setter on Article and add Access to id as follows: