【问题标题】:Mapping Java enum on Postgres enum with EclipseLink使用 EclipseLink 在 Postgres 枚举上映射 Java 枚举
【发布时间】:2012-06-05 13:37:05
【问题描述】:

我第一次尝试使用 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 作为字符串提交没有区别。)

在 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 时,一切都按预期工作。

有什么想法吗?

【问题讨论】:

    标签: postgresql jpa eclipselink


    【解决方案1】:

    为什么要使用@ObjectTypeConverter,您可以使用eclipse 链接开箱即用地映射枚举,如here 所示。 @Enumerated 是 JSR-220 的一部分,而 @ObjectTypeConverterEclipseLink JPA Extensions 的专有扩展。

    @Enumerated(EnumType.STRING)
    @Column(name = "mood")
    private Mood mood;
    

    【讨论】:

    • 这是我目前正在使用的实现。但这要求mood 列是varchar/text/String 类型。
    • 在 postgresql 中将枚举表示为字符串并没有错。
    • 我在想/希望使用枚举类型可以像在字符类型上一样更快地选择/加入它们。
    • 首先,我可能会利用对象关系映射器提供的功能。然后继续进行本机查询或使用数据库优化。
    【解决方案2】:

    尝试删除 @Enumerated( EnumType.STRING ),因为它可能会覆盖转换器设置。

    【讨论】:

    • 很遗憾,这并没有什么不同。
    【解决方案3】:

    什么是心情类型?这不是标准的 JDBC 类型,所以这是您的错误的原因。

    Postgres 如何要求这种类型通过 JDBC 绑定?它不会自动转换 varchar 值似乎很奇怪。 我看了看,它似乎将此类型返回为 PGObject,因此您需要拥有自定义转换器,该转换器可以在您的 Java 枚举和 Postgres 枚举之间进行转换。您还需要在转换器初始化方法中将 DatabaseField 上的 jdbcType 设置为 OTHER。

    请在 EclipseLink 上记录一个错误,以便为这种类型添加到 Postgres 平台的支持。

    我认为禁用参数绑定也可以。

    【讨论】:

    • 这是一个用户(我)定义的枚举。基本上与 Java enum 相同,但在数据库端。所以我的问题实际上是,如何将此用户定义的数据库类型映射到用户定义的 Java 枚举。基本上与这个问题stackoverflow.com/questions/851758/… 相同,但使用 Eclipse/Link 而不是 Hibernate。我已经找到了Converter-Interface,但并不真正了解如何实现它。
    • 你真的不需要转换器。这些例子有点过时了。
    • 要使用转换器,您需要实现自己的转换器类。从仅打印数据库返回的值开始,然后您需要从该值转换为该值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 2017-02-16
    • 1970-01-01
    相关资源
    最近更新 更多