Java Enums, JPA и Postgres enums - Как мне заставить их работать вместе?

String Objects можно проверить, используя этот хак JSON.stringyfy()

var me = new String("me");
var you = new String("me");
var isEquel = JSON.stringify(me) === JSON.stringify(you);
console.log(isEquel);

30
задан Wesley 16 May 2009 в 09:13
поделиться

2 ответа

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

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

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


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

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

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


public @Entity class Person {

  public static enum Mood {sad, ok, happy}

  @Id Long ID;
  Mood mood;

}

К сожалению, JPA не предлагает простой точки перехвата, где вы можете выполнить преобразование из PGObject в Java enum Mood. Однако у большинства поставщиков JPA есть собственная поддержка для этого. Например, Hibernate имеет аннотации 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;

Они позволяют вам предоставить экземпляр 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

}

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

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


public @Entity class Person {

  public static enum Mood {sad, ok, happy}

  @Id Long ID;
  Mood mood;

}

К сожалению, JPA не предлагает простой точки перехвата, где вы можете выполнить преобразование из PGObject в Java enum Mood. Однако у большинства поставщиков JPA есть собственная поддержка для этого. Например, Hibernate имеет аннотации 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;

Они позволяют вам предоставить экземпляр 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

}

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

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


public @Entity class Person {

  public static enum Mood {sad, ok, happy}

  @Id Long ID;
  Mood mood;

}

К сожалению, JPA не предлагает простой точки перехвата, где вы можете выполнить преобразование из PGObject в Java enum Mood. Однако у большинства поставщиков JPA есть собственная поддержка для этого. Например, Hibernate имеет аннотации 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;

Они позволяют вам предоставить экземпляр 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

}

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

JPA не предлагает простой точки перехвата, где вы можете выполнить преобразование из PGObject в Java enum Mood. Однако у большинства поставщиков JPA есть собственная поддержка для этого. Например, Hibernate имеет аннотации 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;

Они позволяют вам предоставить экземпляр 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

}

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

JPA не предлагает простой точки перехвата, где вы можете выполнить преобразование из PGObject в Java enum Mood. Однако у большинства поставщиков JPA есть собственная поддержка для этого. Например, Hibernate имеет аннотации 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;

Они позволяют вам предоставить экземпляр 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

}

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

22
ответ дан 27 November 2019 в 22:31
поделиться

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

Этот патч позволяет мне читать перечисление PostgreSQL в перечисление Java с использованием JPA.

4
ответ дан 27 November 2019 в 22:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: