Я пишу приложение, в котором все свойства String должны быть локализованы, т. Е. Они должны хранить другое значение для каждого доступного Locale. Быстрое решение было бы использовать карту, которая может быть легко переведенный в спящий режим, но это не хорошо на Java программист:Отображение локализованной строки в Hibernate - любая лучшая практика?
public class Product {
private Map<Locale, String> description;
private Map<Locale, String> note;
поэтому я реализовал объект LocalString, который может содержать различные строки для разных районов:
public class LocalString {
private Map<Locale, String> localStrings;
объект домен становится
public class Product {
private LocalString description;
private LocalString note;
Как лучше сопоставить эти объекты с Hibernate аннотации?
Я думаю, что лучшее отображение будет сделано с использованием LocalString в качестве компонента:
@Embeddable
public class LocalString {
private Map<Locale, String> localStrings;
@ElementCollection
public Map<Locale, String> getLocalStrings() {
return localStrings;
}
...
@Entity
public class Product {
private Long id;
private LocalString description;
private LocalString note;
@Embedded
public LocalString getDescription() {
return description;
}
Все нормально, так далеко: hbm2ddl муравья задачи создает две тумбочки, Таблица «Продукты» и таблица «Products_localStrings», которая содержит столбцы ключей и значений. Все ломается, когда я добавляю сорбент для второго свойства:
@Embedded
public LocalString getNote() {
return note;
}
Второе свойство не проявляется в схеме. Я попытался с помощью тегу @AttributesOverride, чтобы определить различные имена для двух столбцов, но генерируемая схема не является правильной:
@Embedded
@AttributeOverrides({
@AttributeOverride(name="localStrings", [email protected](name="description"))
})
public LocalString getDescription() {
return description;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name="localStrings", [email protected](name="note"))
})
public LocalString getNote() {
return note;
}
В сгенерированной схеме столбец ключа исчез и первичный ключ использует «описание» , что является неправильным:
create table Product_localStrings (Product_id bigint not null, note varchar(255), description varchar(255), primary key (Product_id, description));
Любой способ исправить это?
Могу ли я быть лучше без встроенных компонентов, используя LocalString как Entity?
Любые альтернативные проекты?
спасибо.
EDIT
Я попытался с отображением XML, и мне удалось получить правильную схему, но вставки будут выпадать с первичным ключом нарушением, поскольку спящий режим генерирует две вставки вместо одного
<hibernate-mapping>
<class name="com.yr.babka37.demo.entity.Libro" table="LIBRO">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="org.hibernate.id.enhanced.SequenceStyleGenerator"/>
</id>
<property name="titolo" type="java.lang.String">
<column name="TITOLO" />
</property>
<component name="descrizioni" class="com.yr.babka37.entity.LocalString">
<map name="localStrings" table="libro_strings" lazy="true" access="field">
<key>
<column name="ID" />
</key>
<map-key type="java.lang.String"></map-key>
<element type="java.lang.String">
<column name="descrizione" />
</element>
</map>
</component>
<component name="giudizi" class="com.yr.babka37.entity.LocalString">
<map name="localStrings" table="libro_strings" lazy="true" access="field">
<key>
<column name="ID" />
</key>
<map-key type="java.lang.String"></map-key>
<element type="java.lang.String">
<column name="giudizio" />
</element>
</map>
</component>
</class>
</hibernate-mapping>
схема является
create table LIBRO (ID bigint not null auto_increment, TITOLO varchar(255), primary key (ID));
create table libro_strings (ID bigint not null, descrizione varchar(255), idx varchar(255) not null, giudizio varchar(255), primary key (ID, idx));
alter table libro_strings add index FKF576CAC5BCDBA0A4 (ID), add constraint FKF576CAC5BCDBA0A4 foreign key (ID) references LIBRO (ID);
Log:
DEBUG org.hibernate.SQL - insert into libro_strings (ID, idx, descrizione) values (?, ?, ?)
DEBUG org.hibernate.SQL - insert into libro_strings (ID, idx, giudizio) values (?, ?, ?)
WARN o.h.util.JDBCExceptionReporter - SQL Error: 1062, SQLState: 23000
ERROR o.h.util.JDBCExceptionReporter - Duplicate entry '5-ita_ITA' for key 'PRIMARY'
Как мне сообщить, что спящий режим генерирует только одну вставку, как показано ниже?
insert into libro_strings (ID, idx, descrizione, giudizio) values (?, ?, ?, ?)
EDIT на 2011.Apr.05
Я использовал раствор карты на некоторое время (с аннотацией @ElementCollection), пока я не наткнулся на две проблемы:
- Нынешний критерий Критерии не работает во встроенных коллекциях: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3646
- Нынешний API Hibernate Search (Lucene) не работает со встроенными коллекциями: http://opensource.atlassian.com/projects/hibernate/browse/HSEARCH-566
Я знаю, что есть много обходных путей, как с помощью HQL вместо критериев и определения собственного FieldBridge заботиться о карте в Lucene, но мне не нравится обходные пути: они работают, пока следующая проблема не приходит , Так я теперь следующий такой подход:
я определяю класс «LocalString», который содержит локали и значение (Locale на самом деле код ISO3):
@MappedSuperclass
public class LocalString {
private long id;
private String localeCode;
private String value;
Тогда я определить для каждого свойства Я хочу, чтобы локализовать, подкласс LocalString, который является пустым:
@Entity
public class ProductName extends LocalString {
// Just a placeholder to name the table
}
Теперь я могу использовать его в моем объекте продукта:
public class Product {
private Map<String, ProductName> names;
@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
@JoinColumn(name="Product_id")
@MapKey(name="localeCode")
protected Map<String, ProductName> getNames() {
return names;
}
При таком подходе я должен написать пустой класс для каждого свойства, которое мне нужно локализовать, что необходимо для создания уникальной таблицы для этого свойства. Выгода заключается в том, что я могу использовать критерии и поиск без ограничений.
Дальнейшие эксперименты показывают, что AttributeOverrides сворачивает как ключ, так и столбец значений карты в один столбец. – xtian
Я попытался с отображением xml, и мне удалось получить действительную схему, но sql, сгенерированный Hibernate, сохраняет каждое свойство в другой вставке, заканчивая нарушение ограничения первичного ключа. – xtian
Честно говоря, это намного больше, чем у меня есть время на чтение, и я предполагаю, что в него включены несколько вопросов. Вы получаете гораздо лучшую поддержку, когда можете свести проблему к одному вопросу, который легко описать. –