JPA Criteria APIを使用する場合、変数に対してParameterExpressionを直接使用する利点は何ですか?例えば。JPA Criteria APIで変数とParameterExpressionを使用する場合
private List<Customer> findCustomerWithParam(String name) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Customer> criteriaQuery = cb.createQuery(Customer.class);
Root<Customer> customer = criteriaQuery.from(Customer.class);
ParameterExpression<String> nameParameter = cb.parameter(String.class, "name");
criteriaQuery.select(customer).where(cb.equal(customer.get("name"), nameParameter));
return em.createQuery(criteriaQuery).setParameter("name", name).getResultList();
}
簡潔にするため、私は場合は特に、最初の方法を好むだろう:私は文字列変数に名前で顧客を検索したいとき、私はこれになるパラメータを持つ
private List<Customer> findCustomer(String name) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Customer> criteriaQuery = cb.createQuery(Customer.class);
Root<Customer> customer = criteriaQuery.from(Customer.class);
criteriaQuery.select(customer).where(cb.equal(customer.get("name"), name));
return em.createQuery(criteriaQuery).getResultList();
}
のようなものを書くことができますオプションのパラメータでクエリが長くなります。 SQLインジェクションのように、このようなパラメータを使用することの短所はありますか?
を作成しますOpenJPAは内部的にCriteriaクエリーをJPQLに変換し、OpenJPA固有の機能を使用してこれを印刷できることがわかりました(htt p://openjpa.apache.org/builds/2.1.1/apache-openjpa/docs/ch13s03.html)。 最初のクエリは "SELECT c FROM Customer c WHERE c.name = 'test Customer'"に変換されます。つまり、パラメータを使用しないので、さらにSQLに変換された場合、対応するプリペアドステートメントはパラメータを使用しません。 2番目のバージョンはJPQL "SELECT c FROM Customer c WHERE c.name =:name"に変換されるので、パラメータを使用します。 –
もう少しテストを重ねた結果、JPQLで同じクエリを作成し、名前「 'OR' x '=' x」を使用するとJPQLが注入されることがわかりました。基準APIを使用する場合、OpenJPAログが生成するJPQLはまったく同じように見えます。しかし、OpenJPAによって記録された実際のSQLは、JPQLの場合、値「 'OR' x '=' x」の代わりに ''のパラメータを持つ準備済みの文を使用します。つまり、SQLインジェクションはここでは機能しません!残念ながら、これはどれほど信頼できるのか分かりません。これは文書化されていない機能のようです。 –
ヒント:私はちょうどhttp://www.querydsl.com/を試してみました。構文はずっと簡潔で読みやすいです。デフォルトでは、パラメータを使用してSQLインジェクションを防御しているようです。 –