I'm pretty lost with mapping the following structure with JPA annotations.
+===========+ +====================+
| Offer | | Text |
+-----------+ 1 0..* +--------------------+
| id (pk) |-------------| textkey (pk) |
| namekey | | languagecode (pk) |
| ... | | text |
+===========+ | ... |
+====================+
So, each Offer has a name which is i18n-aware. As I have the same cases over and over in the application (Offer also has a i18n comment, Article has a i18n name, etc.) I want to have a Text entity with a composite primary key. For each key there are as many records as there are supported languages. Text samples:
+=====================================+
| textkey | languagecode | text |
+=====================================+
| offer5Name | en | foo |
| offer5Name | fr | bar |
| offer6Name | en | hello |
...
The Offer entity would store Text#textkey in its namekey column.
On the Java side I'd like Offer to have a Set of names or even better a Map of names so I could have a method like Text getName(String language)
instead of Set<Text> getNames()
.
What I already have is Text and its composite primary key TextPK:
@Entity
public class Text {
@EmbeddedId
private TextPK primaryKey;
@Column(name = "text")
private String text;
PK
@Embeddable
public class TextPK implements Serializable {
@Column(name = "textkey")
private Long key;
@Column(name = "languagecode")
@Enumerated(EnumType.STRING)
private LanguageCode languageCode;
Question: how do I annotate the 'names' member variable in the Offer class开发者_运维百科 to get what I need?
Ok, again I'm answering my own question...
JPA 1.0 does not support unidirectional OneToMany (http://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Example_of_a_JPA_2.0_unidirectional_OneToMany_relationship_database) and that's kind of what I would have ended up with.
What worked best for my case was to create an intermediary TextCollection
entity. Each domain entity (such as Offer
) has a OneToOne relationship to a TextCollection
for each of its text attributes (name, description, etc.). The collection entity itself has nothing but an id and bidirectional OneToMany relationship to Text
.
@Entity
@Table(name = "textcollection")
public class TextCollection {
@Id
@Column(name = "textkey")
private String key;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "textCollection")
private final Set<Text> texts = new HashSet<Text>();
@Entity
@Table(name = "text")
public class Text {
@EmbeddedId
private TextPK primaryKey;
@Column(name = "text", nullable = false)
private String text;
@ManyToOne
@JoinColumn(name = "textkey", insertable = false, updatable = false)
private TextCollection textCollection;
@Entity
@Table(name = "offer")
public class Offer {
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "namekey", nullable = false, insertable = true)
private TextCollection name;
精彩评论