2

OpenJPA 1.2.2、WebSphere 7 (Java EE 5)

我正在尝试使用 orm.xml 中定义的命名本机查询将表映射到 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/setter 和空参数构造函数的最终类:

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.

这是什么意思 ?

更多信息:

  • PojoBean 的实现不能更改,并且作为 final 类也不能扩展。
  • 使用 EntityManager.createNativeQuery(...) 从 java 运行查询是可行的,但这不是一个选项。

谢谢,

4

3 回答 3

0

我得到了同样的例外。我的问题是,persistence.xml 中的persistence-unit 名称是错误的。在这种情况下,异常并不完全指向正确的方向......

于 2015-01-30T11:44:18.033 回答
0

问题是 openJPA 不会自动将 underscore_names 映射到 cameCaseName,因此必须提供翻译才能填写您的 POJO。

在您的情况下 col_one => colOne,但 openJPA 不知道这一点。

我所做的是实现通过反射将值分配给相应字段的通用设置器,并在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);
        }

    }   
}
于 2015-02-20T07:30:13.387 回答
0

您可能希望确保已部署 JAR 中的 PojoBean 类实际上具有公共 setter 和 getter。

于 2012-04-04T09:26:10.450 回答