Вопрос по postgresql – Отображение перечисления Java на перечисление Postgres с помощью EclipseLink

2

Я делаю первые попытки с JPA (реализация EclipseLink) и чувствую себя довольно застрявшим:

В PostgreSQL у меня есть следующая схема БД

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

CREATE TABLE person (
  pk      BIGINT   PRIMARY KEY,
  name    VARCHAR  NOT NULL,
  mood    mood     NOT NULL
);

CREATE SEQUENCE person_pk_seq INCREMENT BY 100 MINVALUE 100;

Который работает довольно хорошо, как показывает эта вставкаINSERT INTO PERSON (PK, mood, name) VALUES (3, 'happy', 'Joe') (Передача pk как String не имеет значения.)

Со стороны JPA я написал следующий класс:

package testdb;
import java.io.Serializable;
import javax.persistence.*;
import org.eclipse.persistence.annotations.*;

@Entity
public class Person implements Serializable {
  private static final long serialVersionUID = 1L;

  public enum Mood {
    sad, happy, enthusiastic;
  }

  @Id
  @SequenceGenerator(
    name="PERSON_PK_GENERATOR",
    sequenceName="PERSON_PK_SEQ",
    allocationSize = 100
  )
  @GeneratedValue(
    strategy=GenerationType.SEQUENCE,
    generator="PERSON_PK_GENERATOR"
  )
  public Long pk;

  @Enumerated( EnumType.STRING )
  @Column( name = "mood" )
  @ObjectTypeConverter( name = "moodConverter", objectType = Mood.class,
    dataType = String.class, conversionValues = {
      @ConversionValue( objectValue = "sad", dataValue = "sad" ),
      @ConversionValue( objectValue = "happy", dataValue = "happy" ),
      @ConversionValue( objectValue = "enthusiastic", dataValue = "enthusiastic" )
  })
  @Convert( "moodConverter" )
  public Mood mood;

  @Column( name = "name" )
  public String name;

  public static void main(String[] args) {
    EntityManagerFactory factory = Persistence.createEntityManagerFactory("TestDb.jpa.tests" );
    EntityManager em = factory.createEntityManager();

    em.getTransaction().begin();
    Person p = new Person();
    em.persist( p );
    System.out.println(p.pk);
    p.name = "Joe";
    p.mood = Mood.enthusiastic;
    em.getTransaction().commit();

    Query q = em.createQuery( "select p from Person p" );
    Person x = (Person)q.getResultList().get(0);
    System.out.println( x.pk + " :: " +x.mood );

    em.close();
  }
}

Однако этот пример не работает, и я понятия не имею, в чем проблема:

[EL Warning]: 2012-06-05 15:28:20.646--UnitOfWork(845463623)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.BatchUpdateException: Batch-Eintrag 0 INSERT INTO PERSON (PK, mood, name) VALUES ('801', 'enthusiastic', 'Joe') wurde abgebrochen.  Rufen Sie 'getNextException' auf, um die Ursache zu erfahren.
Error Code: 0
Call: INSERT INTO PERSON (PK, mood, name) VALUES (?, ?, ?)
    bind => [3 parameters bound]

Когда я изменяю тип столбца таблицыperson вvarchar и удалите аннотации@Convert а также@ObjectTypeConverter все работает как положено.

Есть идеи?

Ваш Ответ

3   ответа
0

так как это может привести к переопределению настроек конвертера.

К сожалению, это не имеет значения. Beasterfield
3

Почему ты используешь@ObjectTypeConverter, вы можете отобразить перечисления из коробки со ссылкой затмения, как показаноВо. @Enumerated является частью JSR-220, тогда как@ObjectTypeConverter является проприетарным расширением отEclipseLink JPA Extensions.

@Enumerated(EnumType.STRING)
@Column(name = "mood")
private Mood mood;
Я думал / надеялся, что использование перечислимых типов делает Выбор / Объединение на них быстрее, чем на типах символов. Beasterfield
Во-первых, я мог бы воспользоваться тем, что предлагает объектно-реляционный картограф. Затем перейдите к собственным запросам или используйте оптимизацию базы данных. zellus
Нет ничего плохого в том, чтобы представлять enum как String в postgresql. zellus
Это реализация, которую я использую в настоящее время. Но для этого необходимо, чтоmood столбец имеет тип varchar / text / String. Beasterfield
0

поэтому это причина вашей ошибки.

Как Postgres требует, чтобы этот тип был связан через JDBC? Кажется странным, что он автоматически не конвертирует значения varchar. Я немного посмотрел, и кажется, что этот тип возвращается как PGObject, поэтому вам понадобится собственный конвертер, который преобразует между вашим перечислением Java и перечислением Postgres. Вам также нужно будет установить jdbcType для DatabaseField в вашем методе инициализации конвертеров в значение OTHER.

Пожалуйста, зарегистрируйте ошибку на EclipseLink, чтобы добавить поддержку для платформы Postgres для этого типа.

Я думаю, что отключение привязки параметров также будет работать.

Тебе действительно не нужен конвертер. Примеры немного устарели. zellus
Это определенное пользователем (мной) перечисление. В основном так же, как Javaenum, но на стороне базы данных. Итак, мой вопрос на самом деле заключается в том, как сопоставить этот пользовательский тип базы данных с пользовательским перечислением Java. В основном так же, как в этом вопрос / Stackoverflow.com вопросы / 851758 / ... но используя Eclipse / Link вместо Hibernate. Я нашел ужеConverter -Интерфейс, но не совсем понимаю, как это реализовать. Beasterfield
Чтобы использовать конвертер, вам нужно реализовать свой собственный класс конвертера. Начните с простой печати значения, которое возвращает база данных, затем вам нужно будет преобразовать значение в это значени James

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