web-dev-qa-db-ja.com

条件クエリを使用せずに特定の列のみを選択するJPAクエリ?

たとえば、条件クエリを使用せずにJPAクエリを使用してオブジェクトからプロパティAとBのみを選択することは可能ですか?

すべてのプロパティを選択するには、次のようにします。

SELECT i FROM ObjectName i WHERE i.id = 10

しかし、レガシシステムにmanyプロパティを持つオブジェクトがあり、いくつかのプロパティを選択するのが通常は速いことに気付いていても、いくつかを選択したいだけです。

条件クエリを使用せずにこれは可能ですか?

ありがとうございました!

41
Edy Bourne

はい、プレーンSQLのように、選択するプロパティの種類を指定できます。

SELECT i.firstProperty, i.secondProperty FROM ObjectName i WHERE i.id=10

このクエリを実行すると、Object []のリストが返されます。各配列には、1つのオブジェクトの選択されたプロパティが含まれています。

別の方法は、選択したプロパティをカスタムオブジェクトでラップし、TypedQueryで実行することです。

String query = "SELECT NEW CustomObject(i.firstProperty, i.secondProperty) FROM ObjectName i WHERE i.id=10";
TypedQuery<CustomObject> typedQuery = em.createQuery(query , CustomObject.class);
List<CustomObject> results = typedQuery.getResultList();

例は this の記事にあります。

2018年3月29日更新:

@クリシュ:

@PatrickLeitermannは、「原因:org.hibernate.hql.internal.ast.QuerySyntaxException:クラスを見つけることができません***」という例外を発生させます。これを解決する方法は?

SpringアプリケーションのコンテキストでJPAを使用しているのではないでしょうか。他の一部の人々は正確に 同じ問題 を持ち、彼らの解決策はSELECT NEWキーワードの後に​​完全修飾名(例:com.example.CustomObject)を追加していました。

たぶん、Springデータフレームワークの内部実装は、@ Entityアノテーションが付けられたクラス、または特定のormファイルに単純名で登録されたクラスのみを認識するため、この回避策が使用されます。

83

次のようなものを使用できます。

List<Object[]> list = em.createQuery("SELECT p.field1, p.field2 FROM Entity p").getResultList();

その後、それを繰り返すことができます:

for (Object[] obj : list){
    System.out.println(obj[0]);
    System.out.println(obj[1]);
}

BUTクエリにフィールドが1つしかない場合、Object []からではなくタイプのリストを取得します

17
pL4Gu33

素晴らしい答えです!私は小さな追加があります。このソリューションについて:

TypedQuery<CustomObject> typedQuery = em.createQuery(query , String query = "SELECT NEW CustomObject(i.firstProperty, i.secondProperty) FROM ObjectName i WHERE i.id=100";
TypedQuery<CustomObject> typedQuery = em.createQuery(query , CustomObject.class);
List<CustomObject> results = typedQuery.getResultList();CustomObject.class);

クラスが見つからないというエラーを防ぐには、完全なパッケージ名を挿入するだけです。 org.company.directoryがCustomObjectのパッケージ名であると仮定します:

String query = "SELECT NEW org.company.directory.CustomObject(i.firstProperty, i.secondProperty) FROM ObjectName i WHERE i.id=10";
TypedQuery<CustomObject> typedQuery = em.createQuery(query , CustomObject.class);
List<CustomObject> results = typedQuery.getResultList();
8
sagneta

Projections は、エンティティオブジェクトの特定のプロパティ(列)のみを選択するために使用できます。

ドキュメントから

通常、Spring Data Repositoriesは、クエリメソッドを使用するときにドメインモデルを返します。ただし、場合によっては、さまざまな理由でそのモデルのビューを変更する必要があります。 this セクションでは、リソースの簡略化されたビューと削減されたビューを提供するためのプロジェクションの定義方法を学習します。

必要なgettersのみでインターフェースを定義します。

interface CustomObject {  
    String getA(); // Actual property name is A
    String getB(); // Actual property name is B 
}

次のように、リポジトリからCustomObjectを返します。

public interface YOU_REPOSITORY_NAME extends JpaRepository<YOUR_ENTITY, Long> {
    CustomObject findByObjectName(String name);
}
7
Abdullah Khan

私はあなたの質問を正しく理解していればこのリンクを見ることができると思います http://www.javacodegeeks.com/2012/07/ultimate-jpa-queries-and-tips-list-part_09.html

たとえば、次のようなクエリを作成しました。

 select id, name, age, a.id as ADDRESS_ID, houseNumber, streetName ' +
 20' from person p join address a on a.id = p.address_id where p.id = 1'
0
SerhatCan

はい、可能です。必要なことは、クエリをSELECT i.foo, i.bar FROM ObjectName i WHERE i.id = 10のようなものに変更することだけです。クエリの結果は、Listの配列のObjectになります。各配列の最初の要素はi.fooの値で、2番目の要素はi.barの値です。 JPQLリファレンス の関連セクションを参照してください。

0
ez121sl