您的位置:首页 > 编程语言 > Java开发

Spring Data Jpa系列教程(四)--------高级查询

2018-03-09 15:33 417 查看
    本章介绍一下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 {}好,本节课程就到这里,下课~~~~~~~~~~!!!!!!!!!!!!!!!!!!!!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: