Отображение локализованной строки в Hibernate - какие рекомендации?

Я пишу приложение, в котором все свойства String должны быть локализованы, т.е. они должны хранить разные значения для каждой доступной Locale. Быстрым решением было бы использовать карту, которую можно легко отобразить в Hibernate, но это нехорошо для программиста на Java:

public class Product {
   private Map description;
   private Map note;

Поэтому я реализовал объект LocalString, который может содержать разные строки для разных локалей:

public class LocalString {
   private Map localStrings;

Домен объект становится

public class Product {
   private LocalString description;
   private LocalString note;

Как мне лучше всего сопоставить эти объекты с аннотациями Hibernate?

Я думаю, что лучше всего сопоставить с LocalString в качестве компонента:

@Embeddable
public class LocalString {
    private Map localStrings;

    @ElementCollection
    public Map getLocalStrings() {
       return localStrings;
    }

...

@Entity
public class Product {
   private Long id;
   private LocalString description;
   private LocalString note;

   @Embedded
   public LocalString getDescription() {
          return description;
   }

Пока все в порядке: hbm2ddl Задача ant создает две таблицы: таблицу «Products» и таблицу «Products_localStrings», которая содержит столбцы ключей и значений. Когда я добавляю геттер для второго свойства, все ломается:

   @Embedded
   public LocalString getNote() {
          return note;
   }

Второе свойство не отображается в схеме. Я попытался использовать тег @AttributesOverride, чтобы определить разные имена для двух столбцов, но сгенерированная схема неверна:

   @Embedded
   @AttributeOverrides({
          @AttributeOverride(name="localStrings", column=@Column(name="description"))
   })
   public LocalString getDescription() {
          return description;
   }
   @Embedded
   @AttributeOverrides({
          @AttributeOverride(name="localStrings", column=@Column(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 в качестве объекта?

Какие-либо альтернативные варианты дизайна?

Спасибо.

EDIT

Я пробовал с отображением xml, и мне удалось получить правильную схему, но вставки не работают с нарушением первичного ключа, потому что спящий режим генерирует две вставки вместо одной


    
        
            
            
        
        
            
         
        
        
            
                
            
            
            
                
            
        
        
        
        
            
                
            
            
            
                
            
        
        
    

Схема:

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);

Журнал:

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 (?, ?, ?, ?)

РЕДАКТИРОВАТЬ на 2011. 05 апреля

Я уже некоторое время использую решение Map (с пометкой @ElementCollection),пока я не наткнулся на две проблемы:

Я знаю, что есть много обходных путей, например, использование HQL. критериев и определение вашего собственного FieldBridge для работы с картой в Lucene, но мне не нравятся обходные пути: они работают до тех пор, пока не появится следующая проблема.//opensource.atlassian.com/projects/hibernate/browse/HSEARCH-566

Я знаю, что есть много обходных решений, например, использование HQL вместо критериев и определение собственного FieldBridge для работы с картой в Lucene, но я не Мне не нравятся обходные пути: они работают до тех пор, пока не появится следующая проблема.//opensource.atlassian.com/projects/hibernate/browse/HSEARCH-566

Я знаю, что есть много обходных путей, например, использование HQL вместо критериев и определение собственного FieldBridge для работы с картой в Lucene, но я не Мне не нравятся обходные пути: они работают до тех пор, пока не появится следующая проблема. Итак, теперь я следую этому подходу:

Я определяю класс «LocalString», который содержит языковой стандарт и значение (Локаль фактически является кодом 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
}

Теперь я могу использовать его в своем объекте Product:

public class Product {
   private Map names;

   @OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
   @JoinColumn(name="Product_id")
   @MapKey(name="localeCode")
   protected Map getNames() {
    return names;
  }

При таком подходе мне нужно написать пустой класс для каждого свойства, которое мне нужно локализовать, что необходимо для создания уникального таблица для этого свойства. Преимущество в том, что я могу использовать критерии и поиск без ограничений.

8
задан xtian 6 April 2011 в 09:28
поделиться