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 {}

好,本节课程就到这里,下课~~~~~~~~~~!!!!!!!!!!!!!!!!!!!!


猜你喜欢

转载自blog.csdn.net/qq_32953079/article/details/79496781