In general, you don’t necessarily have to use composite keys in your situation.
You can use just a many-to-many attribute which automatically manages a link table, or, if you need additional attributes in the link table, create a regular entity with a UUID primary key and two foreign keys, plus a unique index on both FKs.
But if you decide to use composite primary key, do it as follows.
Suppose you have User
and Language
entities, both with UUID primary keys.
-
Create an Embeddable entity with two attributes of UUID type:
@JmixEntity
@Embeddable
public class UserLangKey {
@Column(name = "USER_ID", nullable = false)
@NotNull
private UUID user;
@Column(name = "LANGUAGE_ID", nullable = false)
@NotNull
private UUID language;
public UUID getLanguage() {
return language;
}
public void setLanguage(UUID language) {
this.language = language;
}
public UUID getUser() {
return user;
}
public void setUser(UUID userId) {
this.user = userId;
}
@Override
public int hashCode() {
return Objects.hash(language, user);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || ProxyUtils.getUserClass(this) != ProxyUtils.getUserClass(o)) return false;
UserLangKey entity = (UserLangKey) o;
return Objects.equals(this.language, entity.language) &&
Objects.equals(this.user, entity.user);
}
}
-
Create the link entity with the embedded id, add many-to-one attributes and annotate them with @MapsId
:
@JmixEntity
@Table(name = "USER_LANG", indexes = {
@Index(name = "IDX_USER_LANG_USER", columnList = "USER_ID"),
@Index(name = "IDX_USER_LANG_LANGUAGE", columnList = "LANGUAGE_ID")
})
@Entity
public class UserLang {
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "user", column = @Column(name = "USER_ID")),
@AttributeOverride(name = "language", column = @Column(name = "LANGUAGE_ID"))
})
private UserLangKey id;
@MapsId
@JoinColumn(name = "USER_ID", nullable = false)
@NotNull
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private User user;
@MapsId
@JoinColumn(name = "LANGUAGE_ID", nullable = false)
@NotNull
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private Language language;
// other attributes, getters and setters