Отображение карт в Hibernate с использованием JPA2
Я пытаюсь сопоставить java.util.Map с Hibernate, но не могу сделать это правильно. Я использую Hibernate 4.2.8.Final и hibernate3-maven-plugin 2.2. Первоначально я хотел иметь карту с ключом enum-value, с сущностью в качестве значения, но независимо от того, что я пробовал, определение базы данных не получилось с hbm2ddl. Итак, я попробовал простой пример из моей книги JPA2, отображая Map<String, String
, Вот как я это сделал (я использую только аннотации JPA (javax.annotation)):
@ElementCollection
@CollectionTable(name = "coll_table")
@MapKeyColumn(name = "something")
@Column(name = "somethingElse")
public Map<String, String> getSomething() {
return something;
}
При попытке сделать hbm2ddl, это не с:
Execution default-cli of goal org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl failed: Could not determine type for: java.util.Map, at table: SomeTable, for columns: [org.hibernate.mapping.Column(somethingElse)] -> [Help 1]
Итак, я добавил targetClass=String.class
к @ElementCollection
аннотация (хотя это и не нужно). Это не помогает.
Но, возвращаясь к проблеме, которую я пытался решить в первую очередь, отображая с помощью ключа enum и значения сущности.
Это отображение (где LetterType - это перечисление, Letter - это сущность):
@OneToMany
@MapKeyEnumerated(EnumType.ORDINAL)
public Map<LetterType, Letter> getLetters() {
return letter;
}
дает следующий SQL:
create table Application_Letter (
Application_Id int not null,
letter_id int not null,
mapkey varbinary(255) null,
primary key (Application_Id, mapkey),
unique (letter_id)
);
Не шокирующий результат, учитывая мое минимальное отображение (немного странно, что ключ, который был определен как ORDINAL
должен храниться в varbinary(255)
Колонка подумала.) Но когда я пытаюсь расширить с помощью дополнительных опций, я сталкиваюсь с проблемами, я не могу сделать mapkey
столбец получить любое другое имя или тип, независимо от того, что я пытаюсь!
Это отображение (Письмо имеет атрибут type
, типа LetterType):
@OneToMany
@JoinTable(name = "application_letter",
joinColumns = @JoinColumn(name = "app_id"),
inverseJoinColumns = @JoinColumn(name = "letter_id"))
@MapKey(name = "type")
@MapKeyEnumerated(EnumType.STRING)
public Map<LetterType, Letter> getLetters() {
return letters;
}
Урожайность:
create table application_letter (
app_id int not null,
letter_id int not null,
primary key (app_id, letter_id),
unique (letter_id)
);
Так что он слушает некоторые из моих аннотаций, но все-таки неправильно понимает ключевую часть (похоже, он думает, что атрибут id у Letter - это ключ, а не атрибут type, как я указал). Это заставило меня поверить, что что-то не так с использованием enum-значений в качестве ключей, поэтому я попробовал это:
@OneToMany
@JoinTable(name = "application_letter_string",
joinColumns = @JoinColumn(name = "app_id"),
inverseJoinColumns = @JoinColumn(name = "letter_id"))
@MapKeyColumn(name = "letterType")
public Map<String, Letter> getLettersString() {
return lettersString;
}
Теперь я использую String
введите ключ, и, указав его явно, это должно работать. Но нет, результат:
create table application_letter_string (
app_id int not null,
letter_id int not null,
mapkey varchar(255) null,
primary key (app_id, mapkey),
unique (letter_id)
);
По крайней мере, он заметил, что ключ String
и сделал ключевую колонку varchar
, но имя, которое я указал, нигде не видно.
Это подводит меня к моему последнему вопросу: я делаю что-то здесь не так, или Hibernate имеет дело с Map
с просто не работает? (Невозможно создать карту между примитивами, не может создать карту Primitive->Entity, не может создать enum->Entity map, не может создать entityMember->Entity map, осталось не так много вариантов.)