web-dev-qa-db-ja.com

nullの可能性があるSpringデータJPAおよびパラメーター

私の理解では、SpringデータJPAでは、列が特定の非nullメソッドパラメータに等しいすべての行をフェッチし、同じメソッドを使用してメソッドパラメータがnullの場合にこの列がnullのすべての行をフェッチするクエリメソッドを持つことはできません。

あれは正しいですか?

したがって、Javaコードでこれを区別する必要があり、以下の例のように、null値を明示的に要求する別のクエリメソッドを使用する必要がありますか?

// Query methods
List<Something> findByParameter(Parameter parameter);
List<Something> findByParameterIsNull();

...

List<Something> result = new ArrayList<>();

if (parameter == null)
  result = findByParameterIsNull();
else
  result = findByParameter(parameter);

Nullの可能性がある4つのパラメーターがあり、16の異なるクエリメソッドをコーディングする必要がある場合、それは悪いことです。

27
Sebastian S.

あなたが正しいです。

Nullパラメータのより良い処理をサポートするために要求が行われました。 https://jira.spring.io/browse/DATAJPA-121

あなたの場合、私はあなたのリポジトリの実装を書き、カスタム CriteriaQuery を使用してあなたのケースを処理することを勧めます。

また、 @ Query 注釈を is null 構文と共に使用できます。

@Query("[...] where :parameter is null"
public List<Something> getSomethingWithNullParameter();

[〜#〜] edit [〜#〜]

Spring data jpa 2.0以降、springは@Nullableアノテーションをサポートするようになりました。これは、渡されたnullパラメーターを処理するのに役立ちます。

ドキュメント から:

@Nullable – nullの可能性があるパラメーターまたは戻り値で使用されます。

18
Laurent B

例によるクエリ が必要かもしれません。

Query by Exampleは、Spring Dataの新機能( バージョンHopper 、2016年4月リリース)で、次のようなコードで簡単な動的クエリを作成できます。

Person person = new Person();                          
person.setFirstname("Dave");                           

ExampleMatcher matcher = ExampleMatcher.matching()     
  .withIncludeNullValues();                        

Example<Person> example = Example.of(person, matcher);

personRepository.count(example);
personRepository.findOne(example);
personRepository.findAll(example);

count/findOne/findAllのインスタンスをパラメーターとして使用するorg.springframework.data.domain.Exampleメソッド(およびその一部は並べ替え/ページ分割パラメーターも使用)は、org.springframework.data.repository.query.QueryByExampleExecutor<T>によって拡張されるorg.springframework.data.jpa.repository.JpaRepository<T, ID extends Serializable>インターフェイスから提供されます。インタフェース。

つまり、すべてのJpaRepositoryインスタンスにこれらのメソッドが追加されました。

12
mvmn

私は何かを見つけました...あなたがこのようなJPAメソッドにパラメータを入れた場合

@Param("value") String value,

その後、nullになる可能性があり、クエリでは次の状態になります。

(table.value = :value OR :value IS NULL)

値がnullの場合、自動的にtrueを返し、nullでない場合、テーブルでその値を検索します。

5
fvukovic

2018年6月現在、 https://jira.spring.io/browse/DATAJPA-121 を見ると、クエリは自動的にis nullパラメータがnullの場合。

私は私のプロジェクトでそれをしました、それは本当です:

compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '2.0.7.RELEASE'

-

public interface AccountDao extends CrudRepository<T, ID> {

    //this can accept null and it will become isNull
    public List<MyAccount> findByEmail(String email);

}

パラメータがnullの場合:

select
        myaccount0_.id as id1_0_,
        myaccount0_.email as email2_0_,
        myaccount0_.password as password3_0_,
        myaccount0_.user_id as user_id4_0_ 
    from
        my_account myaccount0_ 
    where
        myaccount0_.email is null

パラメータがnullでない場合:

select
        myaccount0_.id as id1_0_,
        myaccount0_.email as email2_0_,
        myaccount0_.password as password3_0_,
        myaccount0_.user_id as user_id4_0_ 
    from
        my_account myaccount0_ 
    where
        myaccount0_.email=?
11:02:41.623 [qtp1507181879-72] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [[email protected]] 

その後、興味深い質問があります。一部の開発者は、クエリのパラメータがnullの場合、クエリのパラメータを無視するように制御することを望んでいますが、これはまだ調査中です https://jira.spring.io/browse/DATAJPA-209

4
GMsoF

私の場合、membershipNumberはnull許容であり、この方法で処理しました。これは、table.membershipNumberがnullであるすべてのケースを処理します。

      @Query(value = "SELECT pr FROM ABCTable pr " +
            "WHERE LOWER(pr.xyz) = LOWER(:xyz) " +
            "and LOWER(pr.subscriptionReference) = LOWER(:subscriptionReference) " +
            "and pr.billId = :billId " +
            "and ((pr.membershipNumber = :membershipId) or (pr.membershipNumber = null and :membershipId = null))")
    List<PaymentRequest> getSomething (@Param("xyz") String xyz,
                                                 @Param("subscriptionReference") String subscriptionReference,
                                                 @Param("billId") Integer billId,
                                                 @Param("membershipId") String membershipNumber);