2020年5月9日 星期六

WHERE條件值使用繫結變量(Bind Variable)

本文為【Spring Boot情境式網站開發指南:使用Spring Data JPA、Spring Security、Spring Web Flow】一書的【 第4章 Criteria API入門】延續,完整範例程式碼可至出版社下載

類似JPQL在查詢本體先以「名稱字串」或「位置數字」作為查詢「替代字符」,後續再以setParameter()方法的繫結該「替代字符」與「真實參數值」,如:
1. 使用名稱字串
Query query = em.createQuery(
    "SELECT e FROM Employee e WHERE e.dept = :deptName" );
query.setParameter("deptName", "IT");
2. 使用位置數字
Query query = em.createQuery(
    "SELECT e FROM Employee e WHERE e.dept = ?1" );
query.setParameter(1, "IT");
Criteria API建立ParameterExpression物件並以泛型指定查詢參數型態作為「替代字符」,後續再以setParameter()方法的繫結該「替代字符」與「真實參數值」。繫結方式也分為兩種,分別示範如下。

使用ParameterExpression的物件參考名稱進行繫結

@Test 
public void Criteria_NoNamedParam() {
    EntityManager em = emf.createEntityManager();
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery sql = cb.createQuery(Employee.class);
    Root emp = sql.from(Employee.class);
    ParameterExpression param = cb.parameter(String.class);
    Expression expr = cb.equal(emp.get(Employee_.name), param);
    sql.select(emp)
        .where(expr);
    TypedQuery typedQuery = em.createQuery(sql);
    typedQuery.setParameter(param, "Jim");
    Employee p = typedQuery.getSingleResult();
    System.out.println(p);
    assertEquals(e1, p);
    em.close();
}
【說明】

  • 行7
使用CriteriaBuilder的parameter()方法並指定參數型態為String以建立ParameterExpression<String>物件,且物件參考名稱為param。
  • 行8
CriteriaQuery的where ()方法依然需要傳入Expression<Boolean>物件,本例使用CriteriaBuilder的equal()方法建構。
    Expression<Boolean>物件的第二個參數過去使用字面常量,使用繫結變量須改傳入ParameterExpression的物件參考param。
    • 行12
    TypedQuery執行查詢時,使用方法setParameter(param, "Jim")指定前述物件參考param與參數值的繫結關係。

    另外指定ParameterExpression物件的參數名稱進行繫結

    測試方法Criteria_NoNamedParam()和Criteria_NamedParam()程式碼大致相同,除了行7特別指定ParameterExpression物件的參數名稱為myName,並於行12使用該名稱myName進行繫結:
    @Test 
    public void Criteria_NamedParam() {
      // the same codes
      ParameterExpression param = cb.parameter(String.class, “myName”);
      // the same codes
      typedQuery.setParameter("myName", "Jim");
      // the same codes
    }
    
    兩者結果不變。

    沒有留言:

    張貼留言