我想在实体bean中使用enum。但是枚举是在一个嵌入对象中。这里有代码:
@Entity
@Table(name = "entity_foo")
public class EntityFoo implements Serializable
{
@Embedded
private EmbeddedFoo embeddedFoo;
public EmbeddedFoo getEmbeddedFoo()
{
return embeddedFoo;
}
public void setEmbeddedFoo(final EmbeddedFoo embeddedFoo)
{
this.embeddedFoo = embeddedFoo;
}
}
我的嵌入式对象包含枚举,看起来像这样:
@Embeddable
public class EmbeddedFoo implements Serializable
{
public static enum EnumBar {
VALUEA,VALUEB
}
private EnumBar enumBar;
@Enumerated(EnumType.STRING)
public EnumBar getEnumBar()
{
return enumBar;
}
public void setEnumBar(final EnumBar enumBar)
{
this.enumBar = enumBar;
}
}
在entity_foo表中,我声明enumbar值为varchar(255)。现在我试着从数据库中获取数据。
final List<EntityFoo> entityFoos = query.getResultList();
抛出一个PSQLException:
Caused by: org.postgresql.util.PSQLException: Bad value for type int : VALUEA
如果我直接在实体"EntityFoo"中使用枚举,它可以正常工作。此代码运行在Wildfly 8.1, Postgres 9.3和Java 1.7
我希望我清楚地说明了我的问题,任何人都可以帮助我。
这是到一个小型项目存储库的链接https://github.com/MotherCake/miniprojct
要使用这个项目,您需要一个表。下面是create语句。
CREATE TABLE "public"."minitable"(id int PRIMARY KEY NOT NULL,enumbar varchar(255));
CREATE UNIQUE INDEX minitable_pkey ON "public"."minitable"(id);
INSERT INTO minitable (id,enumbar) VALUES (0,'VALUEA');
INSERT INTO minitable (id,enumbar) VALUES (1,'VALUEB');
我忘了说的是,我正在使用Toplink。我认为是topplink造成了这个问题。
在Testservlet类中,您可以看到创建查询的两种不同方式。如果我使用createQuery(..)方法和setParameter(..)方法,就会抛出我所描述的异常。这是在评论里。
如果我使用createNativeQuery方法,我得到结果列表,没有异常被抛出。但在此之后,我得到ClassCastException类TestServlet。
问题是默认情况下,使用original将枚举保存为int。您必须通过在enum字段上添加@Enumerated(EnumType.STRING)
来将其更改为字符串表示。还要检查在你的主实体中,你已经注释了字段,而不是getter/setter,所以它打开了对实体以及嵌入式实体的字段访问(在本例中为EmbeddedFoo)。如果你在EmbeddedFoo字段而不是getter中注释它会正确工作。
@Embeddable
public class EmbeddedFoo implements Serializable
{
public static enum EnumBar {
VALUEA,VALUEB
}
@Enumerated(EnumType.STRING)
private EnumBar enumBar;
public EnumBar getEnumBar()
{
return enumBar;
}
public void setEnumBar(final EnumBar enumBar)
{
this.enumBar = enumBar;
}
}
另外,如果你必须在getter上有注释,因为某些原因你必须注释EmbeddedFoo @Access(AccessType.PROPERTY),它也会解决你的问题。
@Embeddable
@Access(AccessType.PROPERTY)
public class EmbeddedFoo implements Serializable
{
public static enum EnumBar {
VALUEA,VALUEB
}
private EnumBar enumBar;
@Enumerated(EnumType.STRING)
public EnumBar getEnumBar()
{
return enumBar;
}
public void setEnumBar(final EnumBar enumBar)
{
this.enumBar = enumBar;
}
}
我找到了一个解决方案来让项目工作,但我不知道为什么这是必要的。我认为,正如Jakub所写的,添加@ EnumType.STRING 应该就足够了。
我用@Column(name = " enumBar ")注释了变量enumBar。
@Column(name = "enumbar")
@Enumerated(EnumType.STRING)
public EnumBar enumBar;
此外,我在EntityFoo
中为嵌入对象添加了@AtributeOverride注释。@Embedded
@AttributeOverride(name = "enumBar", column = @Column(name = "enumbar"))
private EmbeddedFoo embeddedFoo;
之后,它就像魅力一样。
我在github上为每个想尝试的人更新项目。