2

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コンストラクターを備えた最終クラスです。

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

デプロイされたJARのクラスPojoBeanに実際にパブリックセッターとゲッターがあることを確認することをお勧めします。

于 2012-04-04T09:26:10.450 に答える
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 を使用してこれを接続する方法はありますか?

もう 1 つの方法は、すべての 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 に答える