3

我正在使用 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]

当我将表的列类型更改personvarchar并删除注释时@Convert@ObjectTypeConverter一切都按预期工作。

有任何想法吗?

4

3 回答 3

4

为什么使用 a @ObjectTypeConverter,您可以使用 eclipse 链接将 Enumerations 映射到开箱即用,如下所示@Enumerated是 JSR-220 的一部分,而它是EclipseLink JPA Extensions@ObjectTypeConverter的专有扩展。

@Enumerated(EnumType.STRING)
@Column(name = "mood")
private Mood mood;
于 2012-06-06T16:56:11.227 回答
0

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

于 2012-06-06T13:52:12.177 回答
0

What is the mood type? This is not a standard JDBC type, so this is the reason for your error.

How does Postgres require this type to be bound through JDBC? It seems odd it does not auto convert varchar values. I did a little looking, and it seems to return this type as PGObject, so you will need to own custom Converter that converts between your Java enum, and a Postgres enum. You will also need to set the jdbcType on the DatabaseField in your converters init method to OTHER.

Please log a bug on EclipseLink to have support added to the Postgres platform for this type.

I think disabling parameter binding would also work.

于 2012-06-06T14:06:16.763 回答