Spring Data Jpa系列教程(四)--------高級查詢

    本章介紹一下Spring Data Jpa高級查詢,上一章講的JPQL,JPQL使用起來非常方便,但是如果SQL有一個詞不小心寫錯了,只有在程序運行時才能發現錯誤在哪,這是一個弊端,如果想要在編譯器發現錯誤該怎麼做呢,答案是使用Spring Data Jpa高級查詢。

    一、Criteria查詢

@PersistenceContext

private EntityManager entityManager;

    首先注入entityManager

    CriteriaBuilder cb = entityManager.getCriteriaBuilder ();  // criteriaQuery工廠
    CriteriaQuery cq = cb.createQuery(); //查詢語句構造器
    Root<User> root = cq.from(User.class);  //獲取查詢根對象
    cq.select(root);   // select u from User u
    Predicate pre = cb.greaterThan(root.get("age").as(Integer.class), 20); // age大於20
    cq.where(pre); // select u from User u where u.age > 20
    // 上面這一串的目的就是爲了構造出    select u from User u where u.age > 20  的JPQL語句
    Query query = em.createQuery(cq);
    List<User> users = query.getResultList();

這就是一個簡單的Criteria查詢的例子了,下面說一下怎麼使用動態參數,在上方參數20的地方改成:

  Predicate pre = cb.greaterThan(root.get("age").as(Integer.class), cb.parameter(Integer.class, "age"));
    //然後在後面:
    query.setparameter("age",  20);

只查詢部分字段:

    把cq.select(root)改成cq.select(root.get("age"))即可;

    有多個字段就  cq.multiselect(root.get("age"), root.get("name").......)即可;

    此時,結果集映射有兩種方法

    ①List<User> 改成List<Object[]>,手動設置值到實體屬性的映射;

    ②cq.select(cb.construct(User.class, root.get("age"),.......其他字段....)); 使用構造方法自動轉換成實體


Fetch查詢:

    在cq.select 前加上:

  Fetch rootFetch = root.fetch("interests");   // 關聯查詢出用戶的所有性趣

    想要在程序中手動控制fetch,需要先再@ManyToMany等其他註解中將fetch設置成懶加載,然後在程序中控制。

設置JOIN:

    在cq.select前加:

root.join("interests", JoinType.LEFT);  // select u from User u left join u.interests where u.age > 20

結果集排序:

    在cq.orderBy後面:

 cq.orderBy(cb.desc(root.get("age")), cb.asc(root.get("name")));

多個查詢條件:

  Predicate pre = cb.greaterThan(root.get("age").as(Integer.class), 20); // age大於20

    Predicate pre2 = cb.lessThan(root.get("age").as(Integer.class), 40); // age小於20

    cq.where(pre)改成cq.where(pre,pre2);

    也可以使用cb來設置and,or的關係,如;

    cq.where(cb.and(pre, pre2));

    

    二、使用JpaSpecificationExcutor查詢

 public interface UserRepository extends JpaRepository<User, Integer> , JapSpecificationExecutor<User>{

 }

        repository繼承了JapSpecificationExecutor之後,在UserServiceImpl中調用userRepository :

      public List<User> getUsers(){
            return userRepository.findAll(new Specification<User>(){
                  @Override
                    public Predicate toPredicate(Root<User>, CriteriaQuery<?> cq, CriteriaBuilder cb){
                        List<Predicate> preList = new ArrayList();
                        // 跟上面Criteria的條件構造是一樣的
                        // ..........
                        // ..........
                        // 條件構造完畢,都在 preList 裏面
                        return cq.where(preList.toArray(new Predicate[preList.size()])).getRestriction();
                    }            
            }) ;       

        }

    三、@Query和@NamedQuery查詢

    這個註解允許我們在藉口的方法處使用自定義的查詢語句(JPQL或者SQL),

public interface UserRepository extends JpaRepository<User, Integer> , JapSpecificationExecutor<User>{

    @Query(value="select  u from User u where name like ?1") // 這裏可以使用位置參數

    public List<User> findUserByName(String name);

    // @Query(value="select  u from User u where name like :name")  這裏也可以使用命名參數

    // public List<User> findUserByName(@Param("name") String name);


}

    如果想使用原生sql的話,@Query註解裏有一個屬性可以配置:

@Query(value="select  u from user u where name like ?1", nativeQuery = true) // 設置爲true就表示使用原生sql查詢

    @NamedQuery:命名查詢,是調用實體管理器來執行的命名查詢,有一些經常用到的查詢,我們把它先寫好,之後根據名稱直接調用即可。

    @NamedQuery的自定義查詢寫到實體上,

    @NamedQuery(name = "findUserByName", query="select u from User s where u.name like ?1")
    @Entity
    @Table("user")
    public class User {}

    使用實體管理器調用:

  // 使用命名查詢

   entityManager.createNamedQuery("findUserByName");

    query.setParameter(1, "%王%");

    List<User> users = query.getResultList();

    當有多個命名查詢時,可用@NamedQueries包裹起來

 @NamedQueries({
         @NamedQuery(name = "findUserByName", query="select u from User s where u.name like ?1"),
         @NamedQuery(name = "findUserByName2", query="select u from User s where u.name like ?1"),
         @NamedQuery(name = "findUserByName2", query="select u from User s where u.name like ?1")
    })
    @Entity
    @Table("user")
    public class User {}

好,本節課程就到這裏,下課~~~~~~~~~~!!!!!!!!!!!!!!!!!!!!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章