1. 概要

このチュートリアルでは、SpringデータJPAnullパラメーターを処理する方法を示します。

パラメータでレコードを検索する場合、フィールド値としてnullを含む行を検索する場合があります。場合によっては、nullおよびスキップを無視する場合があります。クエリのそのフィールド。

以下に、これらのそれぞれを実装する方法を示します。

2. 簡単な例

Customerエンティティがあるとします。

@Entity
public class Customer {

    @Id
    @GeneratedValue
    private long id;
    private String name;
    private String email;

    public Customer(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // getters/setters

}

また、JPAリポジトリがあります。

public interface CustomerRepository extends JpaRepository<Customer, Long> { 

   // method1
   // method2
}

名前メールで顧客を検索したいと思います。

この目的のために、nullパラメーターを異なる方法で処理する2つのメソッドを記述します。

3. Nullパラメーターの処理方法

まず、パラメータのnull値をISNULLとして解釈するメソッドを作成します。 次に、 null パラメーターを無視し、WHERE句から除外するメソッドを作成します。

3.1. ISNULLクエリ

最初のメソッドは、クエリメソッドのnullパラメータがデフォルトでISNULL として解釈されるため、作成が非常に簡単です。

メソッドを作成しましょう:

List<Customer> findByNameAndEmail(String name, String email);

ここで、 null 電子メールを渡すと、生成されたJPQLには ISNULL条件が含まれます。

customer0_.email is null

これを実証するために、テストを作成しましょう。

まず、リポジトリにいくつかの顧客を追加します。

@Before
public void before() {
    entityManager.persist(new Customer("A", "[email protected]"));
    entityManager.persist(new Customer("D", null));
    entityManager.persist(new Customer("D", "[email protected]"));
}

次に、 name パラメーターの値として“ D” を渡し、emailパラメーターの値としてnullをクエリメソッドに渡します。 。

正確に1人の顧客が見つかることがわかります。

List<Customer> customers = repository.findByNameAndEmail("D", null);

assertEquals(1, customers.size());

Customer actual = customers.get(0);

assertEquals(null, actual.getEmail());
assertEquals("D", actual.getName());

3.2. 別の方法でnullパラメーターを回避する

一部のパラメーターを無視し、対応するフィールドをWHERE句に含めない場合があります。

リポジトリにクエリメソッドを追加できます。

たとえば、 email を無視するために、nameのみを受け入れるメソッドを追加できます。

 List<Customer> findByName(String name);

ただし、列の1つを無視するこの方法は、すべての組み合わせを実現するために多くのメソッドを追加する必要があるため、数が増えるにつれてスケーリングが不十分になります。

3.3. @Queryアノテーションを使用したnullパラメーターの無視

@Query アノテーションを使用し、JPQLステートメントに小さな複雑さを追加することで、追加のメソッドの作成を回避できます。

@Query("SELECT c FROM Customer c WHERE (:name is null or c.name = :name) and (:email is null"
  + " or c.email = :email)")
List<Customer> findCustomerByNameAndEmail(@Param("name") String name, @Param("email") String email);

emailパラメータがnullの場合、句は常に true であるため、WHERE句全体には影響しません。

:email is null or s.email = :email

これが機能することを確認しましょう:

List<Customer> customers = repository.findCustomerByNameAndEmail("D", null);

assertEquals(2, customers.size());

「D」という名前の2人の顧客がメールを無視していることがわかりました。

生成されたJPQLWHERE句は次のようになります。

where (? is null or customer0_.name=?) and (? is null or customer0_.email=?)

この方法では、データベースサーバーを信頼して、クエリパラメーターが null であるという句を認識し、パフォーマンスのオーバーヘッドが大きくならないようにクエリの実行プランを最適化します。 一部のクエリまたはデータベースサーバーでは、特に大規模なテーブルスキャンが含まれる場合、パフォーマンスのオーバーヘッドが発生する可能性があります。

4. 結論

この記事では、SpringDataJPAがクエリメソッドのnullパラメーターを解釈する方法と、デフォルトの動作を変更する方法を示しました。

おそらく将来的には、@NullMeansアノテーションを使用してnullパラメーターを解釈する方法を指定できるようになるでしょう。 これは現時点で提案されている機能であり、まだ検討中であることに注意してください。

要約すると、 null パラメーターを解釈する主な方法は2つあり、どちらも提案された@NullMeansアノテーションによって提供されます。

  • IS(null) –セクション3.1で示したデフォルトのオプション。
  • IGNORED WHERE句からnullパラメーターを除外)–追加のクエリメソッド(セクション3.2。)または回避策(セクション3.3。)のいずれかによって実現されます。 )。

いつものように、完全なソースコードはGitHubから入手できます。