我想在实体bean中使用枚举。但枚举是嵌入式对象。有代码:
@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”中使用枚举,它可以正常工作。此代码在带有Postgres 9.3和Java 1.7的Wildfly 8.1上运行
我希望我能清楚地宣布我的问题,任何人都可以帮助我。
更新
这是微型项目存储库的链接 https://github.com/MotherCake/miniprojct
要使用此项目,您需要一个表格。这是创建语句。
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。我认为Toplink会导致问题。
在Testservlet类中,您可以看到两种不同的方法来创建查询。如果我使用setParameter(..)方法使用createQuery(..)方法,则抛出我描述的异常。这是在评论中。
如果我正在使用createNativeQuery方法,我会得到结果列表并且不会抛出任何异常。但之后我在类TestServlet中得到了ClassCastException。
答案 0 :(得分:1)
问题是默认情况下枚举使用oridinal持久保存为int。您必须通过在枚举字段上添加@Enumerated(EnumType.STRING)
将其更改为字符串表示形式。还要检查主实体中是否有注释字段而不是getter / setter,因此它会在实体和嵌入式实体(在本例中为EmbeddedFoo)上启用FIELD访问。因此,如果您在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上有注释,则必须通过@Access(AccessType.PROPERTY)注释EmbeddedFoo,它也将解决您的问题。
@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;
}
}
答案 1 :(得分:0)
我找到了一个让项目工作的解决方案,但我不知道为什么这是必要的。 正如Jakub写的那样,我认为添加 @Enumerated(EnumType.STRING)就足够了。
我使用@Column(name =“enumbar”)注释变量enumBar。
@Column(name = "enumbar")
@Enumerated(EnumType.STRING)
public EnumBar enumBar;
此外,我将@AtributeOverride注释添加到EntityFoo中的嵌入对象
@Embedded
@AttributeOverride(name = "enumBar", column = @Column(name = "enumbar"))
private EmbeddedFoo embeddedFoo;
之后就像魅力一样。
我在github上为每个想要试用的人更新项目。
感谢您的帮助。