我正在尝试使用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
时,所有内容都按预期工作。
有什么想法吗?
答案 0 :(得分:3)
为什么使用@ObjectTypeConverter
,您可以使用eclipse链接开箱即用地映射枚举here。 @Enumerated
是JSR-220的一部分,而@ObjectTypeConverter
是EclipseLink JPA Extensions的专有扩展。
@Enumerated(EnumType.STRING)
@Column(name = "mood")
private Mood mood;
答案 1 :(得分:0)
尝试删除@Enumerated(EnumType.STRING),因为它可能会覆盖转换器设置。
答案 2 :(得分:0)
心情类型是什么?这不是标准的JDBC类型,因此这就是您的错误原因。
Postgres如何通过JDBC绑定此类型?看起来很奇怪,它不会自动转换varchar值。 我做了一点看,似乎将此类型作为PGObject返回,因此您需要拥有自定义Converter,它可以在您的Java枚举和Postgres枚举之间进行转换。您还需要在converter init方法中将DatabaseField上的jdbcType设置为OTHER。
请在EclipseLink上记录一个错误,以便为此类型的Postgres平台添加支持。
我认为禁用参数绑定也可以。