在我的数据模型中,a有许多实体,其中属性映射到这样的枚举:
@Enumerated(EnumType.STRING)
private MySpecialEnum enumValue;
MySpecialEnum定义了一些固定值。映射工作正常,如果数据库为列保留NULL值,我也会在enumValue属性中获取NULL。 问题是,我的后端模块(我没有影响)使用CHAR列中的空格来标识没有设置值。所以我得到一个IllegalArgumentException而不是NULL值。
所以我的问题是:是否有一个JPA事件,我可以在映射到enum-attribute之前更改从数据库读取的值? 对于写访问,有@PrePersist,我可以在其中将Null值更改为空格。我知道有@ PostLoad事件,但这是在映射后处理的。
顺便说一下:我正在使用WebSphere Application Server中提供的OpenJpa。
答案 0 :(得分:0)
您可以将枚举类型字段映射为@Transient
(它不会被保留)并将另一个字段直接映射为字符串,并在@PostLoad
中同步它们:
@Transient
private MyEnum fieldProxy;
private String fieldDB;
@PostLoad
public void postLoad() {
if (" ".equals(fieldDB))
fieldProxy = null;
else
fieldProxy = MyEnum.valueOf(fieldDB);
}
在Java代码中使用get/setFieldProxy()
。
至于同步另一种方式,我会在setter中而不是@PreUpdate
中进行,因为对@Transient
字段的更改可能不会将实体标记为已修改且更新操作可能不被触发(我不确定):
public void setFieldProxy(MyEnum value) {
fieldProxy = value;
if (fieldProxy == null)
fieldDB = " ";
else
fieldDB = value.name();
}
答案 1 :(得分:0)
OpenJPA提供@Externalizer
和@Factory
来处理“特殊”数据库值。
请参阅:http://ci.apache.org/projects/openjpa/2.0.x/manual/manual.html#ref_guide_pc_extern_values
你可能会得到这样的结论:未经过测试......
@Factory("MyClass.mySpecialEnumFactory")
private MySpecialEnum special;
...
public static MySpecialEnum mySpecialEnumFactory(String external) {
if(StringUtils.isBlank(external) return null; // or why not MySpecialEnum.NONE;
return MySpecialEnum.valueOf(external);
}