Java OpenJpa-创建命名本机查询时出现不可理解的异常

Java OpenJpa-创建命名本机查询时出现不可理解的异常,java,openjpa,Java,Openjpa,OpenJPA1.2.2,WebSphere7(JavaEE5) 我正在尝试使用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

OpenJPA1.2.2,WebSphere7(JavaEE5)

我正在尝试使用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>
创建查询时:

EntityManager myEntityManager = ...
myEntityManager.createNamedQuery("myNativeQuery");
我遇到了一个异常(格式化为可读性):


org.apache.openjpa.persistence.ArgumentException:
结果类型“class foo.bar.PojoBean”没有任何公共字段或用于投影或聚合结果元素“null”的setter方法,
也没有可以使用的通用put(Object,Object)方法,
它也没有接受null类型的公共构造函数。
这意味着什么

更多信息:

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

谢谢,

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

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

我得到了相同的异常。我的例子中的问题是,在persistence.xml中,持久化单元名称是错误的。在这种情况下,expetion并不完全指向正确的方向…

我得到了相同的异常。我的例子中的问题是,在persistence.xml中,持久化单元名称是错误的。在这种情况下,EXCEPTION没有准确地指向正确的方向…

问题是openJPA没有自动将下划线名称映射到cameCaseName,因此您必须提供翻译才能填充POJO

在您的例子中,col_one=>colOne,但openJPA不知道这一点

我所做的是实现一个通用setter,它通过反射将值分配给相应的字段,并得到for string transformation的一点帮助:

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);
        }

    }   
}

问题是openJPA不会自动将下划线_名称映射到cameCaseName,因此您必须提供翻译才能填充POJO

在您的例子中,col_one=>colOne,但openJPA不知道这一点

我所做的是实现一个通用setter,它通过反射将值分配给相应的字段,并得到for string transformation的一点帮助:

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);
        }

    }   
}


你有一个能干的二传手吗?类似于setValue(String val)和setVatue(Integer val)。如果查询返回null,则可能是abigiuos,应该调用哪个setter。不存在不明确的setter。如果我在Java(EntityManager.createNativeQuery(…)上编写查询代码,而不是使用orm.xml,它就可以工作了?另外,您的orm代码段显示您的查询是一个本机查询,为什么不调用createNativeQuery(…)?我还尝试将POPJO设置为非final,没有运气。我不想使用createNativeQuery(…):查询存储在orm.xml中,并根据一些参数(“约定优于配置”)调用。您是否有一个任意的setter?类似于setValue(String val)和setVatue(Integer val)。如果查询返回null,则可能是abigiuos,应该调用哪个setter。不存在不明确的setter。如果我在Java(EntityManager.createNativeQuery(…)上编写查询代码,而不是使用orm.xml,它就可以工作了?另外,您的orm代码段显示您的查询是一个本机查询,为什么不调用createNativeQuery(…)?我还尝试将POPJO设置为非final,没有运气。我不想使用createNativeQuery(…):查询存储在orm.xml中,并根据一些参数(“约定优于配置”)调用。Getter/setter是公共的。如果我像异常中建议的那样手动添加一个通用的“put(Object,Object)”方法,它似乎可以工作,但是这个解决方案是不可接受的。你能检查一下你在Bean中没有使用原语(int,long等)吗。JPA可能会遇到设置null-'对于投影或聚合结果元素“null”'没有原语,bean只使用字符串的问题。数据库(Oracle)中的列也被定义为VARCHAR2。从查询中肯定会返回null。也许您可以在SQL提示符上运行相同的查询,并查看什么是“null”。OpenJPA在设置“null”时遇到问题,即使使用已知的非null值(主键)也无法解决问题。唯一的方法是实现一个甚至不会被调用的伪(空)“put(Object,Object)”方法。但这不是一个解决方案,我不能修改POJO:(Getter/setter是公共的。如果我像异常中建议的那样手动添加一个通用的“put(Object,Object)”方法,它似乎可以工作,但这个解决方案是不可接受的。你能检查一下你没有使用原语(int,long等)吗在Bean.JPA中,可能会遇到为投影或聚合结果元素“null”设置null-'的问题。没有原语,Bean只使用字符串。还有数据库中的列(Oracle)定义为VARCHAR2。查询中肯定返回了null。也许您可以在SQL提示符上运行相同的查询,查看什么是“null”。OpenJPA在设置“null”时遇到问题,即使使用已知为非null的值(主键)也无法解决问题。唯一的方法是实现一个伪值