Перечисления Java, enums JPA и Postgres – Как мне заставить их работать вместе?

У нас есть firebase database postgres с postgres enums. Мы начинаем строить JPA в нашем приложении. У нас также есть enums Java, которые отражают enums postgres. Теперь большой вопрос: как получить JPA, чтобы понять Java enums с одной стороны и postgres enums – с другой? Сторона Java должна быть довольно простой, но я не уверен, как сделать postgres.

Это включает в себя создание нескольких сопоставлений.

Во-первых, перечисление Postgres возвращается драйвером JDBC как экземпляр типа PGObject. Свойство type этого имени имеет имя вашего enums postgres, а значение value – его значение. (Однако порядковый номер не сохраняется, поэтому технически это не переименование и, возможно, совершенно бесполезно из-за этого)

В любом случае, если у вас есть такое определение в Postgres:

CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); 

Затем набор результатов будет содержать PGObject с типом «настроение» и значением «happy» для столбца, имеющего этот тип enums, и строки со значением «happy».

Следующее, что нужно сделать, это написать код перехватчика, который находится между местом, где JPA читает из исходного набора результатов и устанавливает значение для вашей сущности. Например, предположим, что на Java есть следующее лицо:

public @Entity class Person { public static enum Mood {sad, ok, happy} @Id Long ID; Mood mood; }
public @Entity class Person { public static enum Mood {sad, ok, happy} @Id Long ID; Mood mood; } 

К сожалению, JPA не предлагает простой точки перехвата, где вы можете выполнить преобразование из PGObject в Java enum Mood. Тем не менее, большинство поставщиков JPA имеют некоторую проприетарную поддержку для этого. Например, Hibernate имеет annotations TypeDef и Type для этого (из Hibernate-annotations.jar).

@TypeDef(name="myEnumConverter", typeClass=MyEnumConverter.class) public @Entity class Person { public static enum Mood {sad, ok, happy} @Id Long ID; @Type(type="myEnumConverter") Mood mood;
@TypeDef(name="myEnumConverter", typeClass=MyEnumConverter.class) public @Entity class Person { public static enum Mood {sad, ok, happy} @Id Long ID; @Type(type="myEnumConverter") Mood mood; 

Они позволяют вам предоставить экземпляр UserType (из Hibernate-core.jar), который выполняет фактическое преобразование:

public class MyEnumConverter implements UserType { private static final int[] SQL_TYPES = new int[]{Types.OTHER}; public Object nullSafeGet(ResultSet arg0, String[] arg1, Object arg2) throws HibernateException, SQLException { Object pgObject = arg0.getObject(X); // X is the column containing the enum try { Method valueMethod = pgObject.getClass().getMethod("getValue"); String value = (String)valueMethod.invoke(pgObject); return Mood.valueOf(value); } catch (Exception e) { e.printStackTrace(); } return null; } public int[] sqlTypes() { return SQL_TYPES; } // Rest of methods omitted }
public class MyEnumConverter implements UserType { private static final int[] SQL_TYPES = new int[]{Types.OTHER}; public Object nullSafeGet(ResultSet arg0, String[] arg1, Object arg2) throws HibernateException, SQLException { Object pgObject = arg0.getObject(X); // X is the column containing the enum try { Method valueMethod = pgObject.getClass().getMethod("getValue"); String value = (String)valueMethod.invoke(pgObject); return Mood.valueOf(value); } catch (Exception e) { e.printStackTrace(); } return null; } public int[] sqlTypes() { return SQL_TYPES; } // Rest of methods omitted } 

Это не полное рабочее решение, а просто быстрый указатель в надежде на правильное направление.

Я фактически использовал более простой способ, чем тот, что с PGObject и Converters. Так как в Postgres enums преобразуются вполне естественно в текст, вам просто нужно позволить ему делать то, что он делает лучше всего. Я возьму пример Арджана настроений, если он не возражает:

Тип enums в Postgres:

 CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); 

Класс и перечисление в Java:

 public @Entity class Person { public static enum Mood {sad, ok, happy}; @Enumerated(EnumType.STRING) Mood mood; 

}

Этот тег @Enumerated указывает, что сериализация / десериализация enums должна выполняться в тексте. Без него он использует int, что более сложно, чем что-либо.

На этом этапе у вас есть два варианта. Вы либо:

  1. Добавьте stringtype = unspecified в строку подключения, как описано в параметрах соединения JDBC . Это позволяет Postgres угадывать правый тип и полностью преобразовывать все, так как он получает что-то вроде «enum = unknown», которое является выражением, которое он уже знает, что делать (передать значение? В десериализатор левого типа). Это предпочтительный вариант, так как он должен работать для всех простых UDT, таких как enums за один раз.

Или:

  1. Создайте неявное преобразование из varchar в enum в базе данных. Таким образом, в этом втором случае firebase database получает некоторое присвоение или сравнение, например «enum = varchar», и находит в своем внутреннем каталоге правило о том, что оно может передавать правое значение через функцию сериализации varchar, за которой следует функция десериализации ENUM. Это больше шагов, чем нужно; и наличие слишком большого количества неявных бросков в каталоге может привести к неоднозначным интерпретациям произвольных запросов, поэтому используйте их экономно. Создание роли:

    СОЗДАЙТЕ CAST (ХАРАКТЕР ВРАЩАЮТСЯ как настроение), НЕ НЕЗАВИСИМО ОТ КАКОЙ-ЛИБО;

Должен работать именно так.

Я подал сообщение об ошибке с патчем, включенным в Hibernate: HHH-5188

Патч работает для меня, чтобы прочитать перечисление PostgreSQL в перечисление Java, используя JPA.

  • Понимание размеров строк Postgres
  • Возвращать строки, соответствующие элементам входного массива в функции plpgsql
  • Что такое «$$», используемое в PL / pgSQL
  • Поддержка SQLAlchemy схем Postgres
  • PostgreSQL: разница между текстом и varchar (характер меняется)
  • Сопоставление массива PostgreSQL с Hibernate
  • Использование Hibernate последовательности PostgreSQL не влияет на таблицу последовательности
  • Postgres sql вставляет запрос синтаксиса запроса из phpPgAdmin
  • Postgres не удалось подключиться к серверу
  • Измерение петли по размеру массива в plpgsql
  • Являются ли функции PostgreSQL транзакционными?
  • Interesting Posts

    Каков разумный порядок модификаторов Java (абстрактный, окончательный, общеansible, статический и т. Д.)?

    5 Максимальное подключение / подключение к Интернету? Мой провайдер ограничивает меня каким-то образом?

    Ошибка соединения Bluetooth “java.io.IOException: чтение не выполнено, сокет может быть закрыт или таймаут, read ret: -1”

    Реализация вложенных функций

    Определение, является ли число простым

    Как сортировать хеш perl по значениям и заказывать ключи соответственно (возможно, в двух массивах)?

    Получить конкретный элемент ArrayList

    Oracle эквивалентен MySQL INSERT IGNORE?

    Как обращаться с десериализацией с polymorphismом?

    Изменение реестра для увеличения тайм-аута графического процессора, Windows 7

    Облачные функции для Firebase – учетная запись не настроена

    Могу ли я использовать Google Apps Sync для Outlook исключительно как инструмент синхронизации, а не для миграции электронной почты?

    Как я могу предотвратить изменение размера windows с помощью tkinter?

    Тип массива – правила для назначения / использования в качестве параметра функции

    Обнаружение при подключении головных телефонов

    Давайте будем гением компьютера.