Я немного прочитал об этой теме c и нашел решение, но мне интересно, есть ли более точное или более оптимальное решение.
Мое основное требование c - создать объект, который имеет карту списков типа string, ie:
private Map<String, List<String>> mapOfStringLists;
Важно, что мы можем эффективно запрашивать сущности, которые содержат определенную c пару имя-значение, ie. где mapOfStringLists.get(K).contains(V)
;
Подход, который я до сих пор использовал, заключается в создании промежуточного объекта для представления сопоставленных элементов, а затем в нем набора строковых элементов. Это требует двух таблиц, где логически должна быть только одна (на мой взгляд).
Java код:
@Entity
@Table(name = "T_USER_PROFILE")
public class UserProfile {
@OneToMany(targetEntity = UserProfileAttributeMultiValued.class, mappedBy = "userProfile")
@MapKeyColumn(name = "ATTRIBUTE_NAME")
private Map<String, UserProfileAttributeMultiValued> attributesMultiValued = new HashMap<>();
}
@Entity(name = "T_USER_PROFILE_ATTRIBUTE_MV")
public class UserProfileAttributeMultiValued {
@EmbeddedId
private MultiValuedUserProfileAttributeKey key;
@ElementCollection
@CollectionTable(name = "T_USER_PROFILE_ATTRIBUTE_MV_VALUES", joinColumns = {
@JoinColumn(name = "USER_PROFILE_GUID_FK"),
@JoinColumn(name = "ATTRIBUTE_NAME")
})
public List<String> values;
@ManyToOne
@JoinColumn(name = "USER_PROFILE_GUID_FK", nullable = false, insertable = false, updatable = false)
private UserProfile userProfile;
}
@Embeddable
public class MultiValuedUserProfileAttributeKey implements Serializable {
@Column(name = "USER_PROFILE_GUID_FK", length = 36)
private String guid;
@Column(name = "ATTRIBUTE_NAME")
private String attributeName;
}
Сгенерированная схема:
create table T_USER_PROFILE (
GUID varchar(36) not null,
primary key (GUID)
);
create table T_USER_PROFILE_ATTRIBUTE_MV (
USER_PROFILE_GUID_FK varchar(36) not null,
ATTRIBUTE_NAME varchar(255) not null,
primary key (ATTRIBUTE_NAME, USER_PROFILE_GUID_FK)
);
create table T_USER_PROFILE_ATTRIBUTE_MV_VALUES (
USER_PROFILE_GUID_FK varchar(255) not null,
ATTRIBUTE_NAME varchar(36) not null,
values varchar(255)
);
Это является достаточно аккуратным и логичным, и я могу понять, что промежуточная таблица может быть необходима для того, чтобы иметь четкий (составной) первичный ключ для набора элементов, но, возможно, есть лучший способ скрыться?
Спасибо