余計なエンティティの作成を避けるにはどうすればよいですか?

私の現在のプロジェクトでは、クエリで結合されたテーブルからいくつかのフィールドを選択するネイティブクエリをいくつか実行する必要があります。

SELECT t1.col1, t2.col5
FROM t1
JOIN t2 ON t2.id = t1.t2_id

私はそれらをクラスのように保管しようとしました。

class Result {
  String t1_col1;
  String t2_col5;
}

を使用して

Query q = entityManager.createNativeQuery( "THE SQL SELECT" , Result.class );

JPAは現在、クラス 'result'がオブジェクトに列をマップするためにおそらく必要となるエンティティではないと不平を言う(「未知のエンティティ:結果」)。 また、結果クラスで @Column 宣言を繰り返そうとしました。

私の質問は、どのように私のDBにテーブルとして表現されたentitesを作成することなくこれを宣言することができますか?

6

4 答え

ああ、私はJPAでそれを行う方法はありません。しかし、これはハイバネートの Query オブジェクトで行うことができます。それを得るには:

org.hibernate.Query query = q.unwrap(org.hibernate.Query.class);

そして、結果変換を設定します。 こちらをご覧ください

query.setResultTransformer(Transformers.aliasToBean(Result.class));
6
追加された
@downvoter - なぜですか?
追加された 著者 Bozho,

JPA/Hibernateを使用してSQLクエリを実行している場合は、誤ったツールを使用しています。 HibernateはORMであり、テーブルをエンティティにマップすることになっています。それがJPAの要点です。私は、SQLクエリを実行したいだけで、JDBC(とSpringのJdbcTemplateなど)

table1とtable2がエンティティにマッピングされると(これらのエンティティT1とT2を呼ぶ)、JPQLはエンティティの一部のフィールドだけを選択できるので、これらのSQLクエリはもう必要ありません。クエリは次のようになります(t1とt2の間の関連性によって異なります)。

select t1.col1, t2.col5 from T1 t1 join t1.t2 t2

そして結果(DTOでありマッピングされたエンティティではありません)を構築するために、結果(Object [])のリストを反復するだけです。

List rows = (List) query.list();
List listOfResults = new ArrayList(rows.size);
for (Object[] row : rows) {
    listOfResults.add(new Result((String) row[0], (String) row[1]));
}
5
追加された
これは質問が尋ねたことではありませんでした。ネイティブクエリーの解決策を求めていました。
追加された 著者 BillR,
あなたは典型的なORMペダンティックな答えを提供しました。私はそれが最善の答えであるかどうかわかりません。私はORMがすべてで終わりとはみなされません。彼は実際に質問に答えることを望んでいた誰も見つけられなかったので、それを受け入れることができ、二次的な答えを解決しなければならなかった。私は同じ質問をしており、ここでは答えられませんでした。それがここで答えたのを見てうれしい。他にも何百万ものORMペタンティックポストがあり、同じことが言えます。しかし私はクールドードを飲むのを拒否し、グループの考えに従うだけでなく、私が最良の解決策であると考えるものを使用します。 5年後にORM will = XMLになります。
追加された 著者 BillR,
「休止状態」というだけで、JPAはORMを使用してすべてのエンティティにマップする必要はありません。人々は、ネイティブクエリも作成するためにhibernateを使用します。 'ORM only'が最善の場合、Hibernateの開発者は "createSQLQuery"(JPA以外のネイティブクエリー)を実装するのに悩まされていると思いますか?彼らはORMを使用することだけが反パターンかもしれないことを認識しています。しかし丸い穴があっても誰もが同じ正方形のORMペグを使いたいと思っています。それについて考えると、Hibernateはネイティブクエリをサポートしています。どうして? ...だから誰かがネイティブクエリの問題を解決する方法を尋ねるとき...それはすべて私が言うつもりです。
追加された 著者 BillR,
ええ、私はそれを知っているが、それは恐ろしいことを見つける。これはリファクタリングを許可せず、2〜3つの些細なコード行しか保存しません。さらに、デバッグが難しくなります。
追加された 著者 JB Nizet,
コンストラクタに引数を追加すると、上記のコードはコンパイルを停止し、クエリを修正する必要があることがわかります。 JPQLクエリで新しいものを使用すると、実行時に例外が発生します。私がコンストラクタ内の引数の順序を切り替えると、私のIDEはすべての呼び出しを切り替えます。しかし、新しいものがJPQLにある場合はそうではありません。私のクエリが間違った型を返した場合、わかりやすい "コンストラクタを見つけることができません"という例外ではなく、ClassCastExceptionが発生します。クエリの結果を調べて、何が間違っているかを確認することができます。
追加された 著者 JB Nizet,
@ビル:しかし、OPは答えを受け入れた。誰かがドライバーで釘を動かす方法を尋ねるとき、最良の答えは、このようにしないでください。ハンマーを使用してください。
追加された 著者 JB Nizet,
@BillR:質問にはJPAとHibernateのタグが付いています。 JPAとHibernateを使用するためにOP を選択しました。 ORMが良いと思わない場合は、JPAとHibernateを使用しないでください。 ORMを使用する必要はありません。しかし、ORMの使用を選択した場合は、ルールを実行する必要があります。 ORMが嫌いなだけで私の答えが間違っているとは限りません。
追加された 著者 JB Nizet,
合意した小さな(しかし素晴らしい)機能を追加するには、次のようにJPQLクエリでNEW演算子を使用できます。SELECT NEW com.Result(t1.col1、t2.col5)FROM T1 t1 join t1.t2 t2 Result(String、String)コンストラクタを呼び出すと、Entity自体である必要のない新しいResultオブジェクトを作成するために呼び出されます。
追加された 著者 Piotr Nowicki,
「リファクタリングを許可しない」とはどういう意味ですか?パラメータまたはそのタイプがNEW構造を使用していないか使用していない場合よりも変化した場合は、あなたを節約します。私はそれがCriteria APIのようなトレードオフの問題だと思う。それはもっとリファクタリングが容易だが個人的に私のために読むのは難しい。
追加された 著者 Piotr Nowicki,
良い点、明確化のために感謝:-)
追加された 著者 Piotr Nowicki,

私はDataNucleus JPAで(わずかな変更を加えて)そのクエリを実行することができ、JPA仕様に準拠する必要があるので、うまく動作します。

SELECT t1.col1 AS t1_col1, t2.col5 AS t2_col5 FROM t1 JOIN t2 ON t2.id = t1.t2_id

つまり、結果クラス内のフィールド名とリターン列を整列させます。 JPA仕様では、結果クラスがEntityクラスである必要があるとは言えません。単に「結果のインスタンスのクラス」と表示されます。

1
追加された

問合せから必要な結合列を戻し、データ所有者クラスのビュー名を使用するVIEWを定義することができます。

0
追加された