Как я могу реализовать I18n как объект JSON для сущности JPA или Hibernate? - PullRequest
1 голос
/ 16 июня 2020

У меня есть приложение Spring-boot, которое использует JPA и Hibernate. Вы можете найти весь код в этом репозитории GitHub .

Мой вопрос в том, как добавить функциональность интернационализации в указанный столбец c без каких-либо внешних ключей и с использованием структуры JSON ?

Например, я хотел бы определить объект JPA следующим образом:

@Entity
class Book {

    @Id
    private int id;

    private Author author;

    @I18n  //<- this annotation is something that I am looking for 
    private String title;

}

, и тогда данные в столбце title будут сохранены, как показано ниже, для en и de locales:

{"en":"Cologne","de":"Köln"}

А затем, когда текущая локаль de, Köln и когда en установлен как локаль, тогда Cologne извлекается во время чтения данных!

Также, когда мы сохраняем данные, переданная строка сохраняется в соответствующем свойстве в формате JSON. Например, если локаль установлена ​​на es, а пользователь передает Kolne, тогда у нас должны быть следующие данные в БД:

{"en":"Cologne","de":"Köln","es":"Kolne"}

Мне интересно, что большинство решений в web для гибернации, а JPA основан на старом методе с использованием таблиц languages и translations. Что-то вроде здесь или здесь .

Однако я ищу некоторые решения, такие как этот , который предлагается для Laravel и сохраните переводы точно так, как я объяснил (т.е. в объекте JSON и в том же столбце)!

Единственное решение, которое я нашел и которое может быть каким-то образом релевантным (не 100%), - этот , однако он не работает, когда я пытался его протестировать, и, похоже, он больше не поддерживается!

1 Ответ

1 голос
/ 18 июня 2020

Поскольку это очень распространенное требование, этот ответ основан на этой статье , которую я написал в своем блоге, в которой объясняется, как проект Hibernate Types добавляет поддержку для сопоставления атрибутов Map сущностей как JSON типы столбцов.

Проект типов гибернации

Во-первых, вам необходимо добавить зависимость проекта Тип гибернации .

После этого, вы можете использовать либо столбец HStore , либо столбец JSONB для хранения названий с указанием местоположения c:

@Entity
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
class Book {

    @Id
    private int id;

    private Author author;

    @Type(type = "jsonb")
    @Column(name = "localized_titles", columnDefinition = "jsonb")
    private Map<String, String> localizedTitles = new HashMap<>();

    public String getLocalizedTitle(String locale) {
        return localizedTitles.get(locale);
    }

    public String getLocalizedTitle() {
        return localizedTitles.get(LocaleUtil.getDefaultLocale());
    }
}

Итак, вы можете вызвать getLocalizedTitle и передать текущий языковой стандарт, чтобы получить текущий локализованный заголовок.

Book book = entityManager.find(Book.class, bookId);
String title = book.getLocalizedTitle("en");

Или вы можете сохранить текущий языковой стандарт в ThreadLocal в классе с именем LocaleUtil:

public class LocaleUtil {
  
    private static final ThreadLocal<String> LOCALE_HOLDER =
        new ThreadLocal<>();

    public static String getLocale() {
        return LOCALE_HOLDER.get();
    }
 
    public static void setLocale(String locale) {
        LOCALE_HOLDER.set(locale);
    }
 
    public static void reset() {
        LOCALE_HOLDER.remove();
    }
}

И сохраните текущую локаль следующим образом:

LocaleUtil.setLocale("en");

И затем просто вызовите getLocalizedTitle метод, который не принимает аргументов:

Book book = entityManager.find(Book.class, bookId);
String title = book.getLocalizedTitle();

Проверить этот PostgreSQLJsonMapTest тестовый пример на GitHub для получения дополнительных сведений об использовании типов гибернации для сохранения e Java Map как JSON типы столбцов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...