OpenJPA 1.2.2,WebSphere 7(Java EE 5)
我正在尝试使用orm.xml中定义的named-native-query将表映射到POJO(非实体!):
<named-native-query name="myNativeQuery" result-class="foo.bar.PojoBean">
<query>
SELECT col_one AS colOne, col_two AS colTwo, col_three AS colThree
FROM myTable WHERE id = 42
</query>
</named-native-query>
PojoBean是一个带有String getter / setters和empty-argument构造函数的final类:
public final class PojoBean implements java.io.Serializable {
public PojoBean() {
}
public String getColOne() { ... }
public void setColOne(String colOne) { ... }
...
}
创建查询时:
EntityManager myEntityManager = ...
myEntityManager.createNamedQuery("myNativeQuery");
我有一个例外(格式化的可读性):
<openjpa-1.2.2-r422266:898935 nonfatal user error>
org.apache.openjpa.persistence.ArgumentException:
Result type "class foo.bar.PojoBean" does not have any public fields or setter methods for the projection or aggregate result element "null",
nor does it have a generic put(Object,Object) method that can be used,
nor does it have a public constructor that takes the types null.
这意味着什么?
更多信息:
谢谢,
答案 0 :(得分:0)
您可能希望确保已部署的JAR中的类PojoBean实际上具有公共setter&amp;吸气剂。
答案 1 :(得分:0)
我得到了同样的例外。我的问题是,在persistence.xml中,持久性单元名称是错误的。在这种情况下,激发并没有完全指向正确的方向......
答案 2 :(得分:0)
问题是openJPA不会将underscore_names自动映射到cameCaseName,因此你必须提供翻译以填充您的POJO。
在你的情况下col_one =&gt; colOne,但openJPA不知道。
我所做的是实现通用反射器将值分配给相应字段的通用setter,并在Google Guava的帮助下进行字符串转换:
public void put(Object field, Object value) {
try {
String fieldName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, field.toString());
Field f = this.getClass().getDeclaredField(fieldName);
f.set(this, value);
}
catch(Exception e) {
logger.error("ERROR: " + e.getMessage());
}
}
我必须说我不太喜欢这个解决方案,但它的工作非常好。有没有办法实现某个接口或使用@Annotation连接它?
另一种方法是使用每个pojo扩展的抽象类。在这种情况下,您应该使用setter方法,因为该字段可能是私有的。
public abstract class JpaPutter {
public void put(Object field, Object value) {
try {
String methodName = "set" + CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, field.toString());
this.getClass().getMethod(methodName, value.getClass()).invoke(this, value);
}
catch(Exception e) {
throw new RuntimeException(e);
}
}
}