Spring Boot 学习研究笔记(十七) -Spring boot JPA的复杂查询

简介: Spring Boot 学习研究笔记(十七) -Spring boot JPA的复杂查询

Spring boot JPA的复杂查询

 

一、 JpaSpecificationExecutor 接口查询方式

1、JpaSpecificationExecutor接口

JPA 提供动态接口JpaSpecificationExecutor,利用类型检查的方式,利用Specification进行复杂的条件查询,比自己写 SQL 更加便捷和安全。

JpaSpecificationExecutor 源码

public interface JpaSpecificationExecutor<T> {
    /**
     * Returns a single entity matching the given {@link Specification}.
     * 
     * @param spec
     * @return
     */
    T findOne(Specification<T> spec);
    /**
     * Returns all entities matching the given {@link Specification}.
     * 
     * @param spec
     * @return
     */
    List<T> findAll(Specification<T> spec);
    /**
     * Returns a {@link Page} of entities matching the given {@link Specification}.
     * 
     * @param spec
     * @param pageable
     * @return
     */
    Page<T> findAll(Specification<T> spec, Pageable pageable);
    /**
     * Returns all entities matching the given {@link Specification} and {@link Sort}.
     * 
     * @param spec
     * @param sort
     * @return
     */
    List<T> findAll(Specification<T> spec, Sort sort);
    /**
     * Returns the number of instances that the given {@link Specification} will return.
     * 
     * @param spec the {@link Specification} to count instances for
     * @return the number of instances
     */
    long count(Specification<T> spec);
}

2、Specification 说明

Specification是我们传入进去的查询参数,是一个接口,并且只有一个方法。

public interface Specification<T> {
    Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}

3、toPredicate 函数参数说明:

  • Root: 是查询结果的一个实体对象,也就是查询结果返回的主要对象。

root = query.from(User.class);

  •  
  • CriteriaQuery:是JPA标准,主要是构建查询条件的,里面的方法都是各种查询方式:distinct、select、where、groupby、having、orderby这些方法。

// query = cb.createQuery(User.class);//

  •  
  • CriteriaBuilder:主要用来生成Predicate接口 。其中包含between、gt(大于)、lt(小于)、not(非)等等操作。

4、JpaSpecificationExecutor 内部查询原理

第一步,使用EntityManager 获得 CriteriaBuilder 查询工厂;

第二步,使用 CriteriaBuilder 获得查询类 CriteriaQuery;

第三步,组装查询条件数组 List<Predicate> ;

第四步,使用CriteriaQuery where 拼接 or 或and + 条件数组;

第五步,使用 EntityManager 进行查询;

 

重点说一下

JPA标准中Hibernate的两个实现方法:

org.hibernate.ejb.criteria.CriteriaBuilderImpl.and(Predicate...)

org.hibernate.ejb.criteria.CriteriaBuilderImpl.or(Predicate...)

这两个方法都有一个关键的接口: Predicate(javax.persistence.criteria.Predicate)

这个接口同为Expression的子接口,作为关联各种Predicate的核心操作接口:

and:是将各个条件作为and来拼接,进行查询。

or:是将各条件作为or来拼接,进行查询。

 

代码演示查询流程

@PersistenceContext
private EntityManager em;
@Override
public List<Even> list(Even even) {
    //查询工厂
    CriteriaBuilder cb = em.getCriteriaBuilder();
    //查询类
    CriteriaQuery<Even> query = cb.createQuery(Even.class);
    //查询条件
    List<Predicate> predicates = new LinkedList<>();
    //查询条件设置
    predicates.add(cb.equal("id", even.getId()));
    predicates.add(cb.like("eventTitle", even.getEventTitle()));
    //拼接where查询
    query.where(cb.or(predicates.toArray(new Predicate[predicates.size()])));
    //用JPA 2.0的TypedQuery进行查询
    TypedQuery<Even> typedQuery = em.createQuery(query);
    return typedQuery.getResultList();
}

 

5 、使用步骤:

(1)、对应的Repository需要实现JpaSpecificationExecutor接口

public interface UserRepository extends JpaRepository<User, Long> ,

           JpaSpecificationExecutor<User>{

 

(2)、在业务层编写你具体的复杂查询语句

新建一个条件构造器,重写oPredicate方法:

@Override
    public Page<泛型> findRecordList(int couponDetailId, int pageNum, int pageSize, String startTime, String endTime) {
        try {
        //排序规则和分页
            Sort sort = new Sort(new Sort.Order(Sort.Direction.DESC, "createTime"));
            PageRequest pageRequest = new PageRequest(pageNum - 1, pageSize, sort);
            Specification specification = new Specification() {
                @Override
                public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
            //增加筛选条件
                    Predicate predicate = cb.conjunction();
                    predicate.getExpressions().add(cb.equal(root.get("cardId"), couponDetailId));
            //起始日期
                    if (startTime != null && !startTime.trim().equals("")) {
                        predicate.getExpressions().add(cb.greaterThanOrEqualTo(root.get("createTime").as(String.class), startTime));
                    }
            //结束日期
                    if (endTime != null && !endTime.trim().equals("")) {
                        predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get("createTime").as(String.class), endTime));
                    }
                    return predicate;
                }
            };
            Page all = discountCouponRecordDao.findAll(specification, pageRequest);
  return all;
}

 

二、自定义SQL

JPA同样允许自己写SQL操作记录。

实例:

接口:

@Query(value = "select * from order_info where user_name = ?1 and user_address = ?2", nativeQuery = true)

List<Order> selectByNameAndAddress(String name, String address);


@Modifying

@Transactional

@Query(value = "update order_info set user_address = ?1 where order_id = ?2", nativeQuery = true)

void updateAddressByOrderId(String address, Integer orderId);

注意: 1). 自定义SQL可以随便命名方法名

2).需要用@Query注解,如果是更新删除操作还需要有 @Modifying@Transactional 注解

3). SQL里的?表示的占位符,编译和执行的时候,取值是取接口的入参,?后的数字是第几个参数,从0开始


相关文章
|
1月前
|
安全 Java Apache
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
80 0
|
1月前
|
安全 Java 数据安全/隐私保护
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
85 0
|
5天前
|
Java Spring
Spring框架的学习与应用
总的来说,Spring框架是Java开发中的一把强大的工具。通过理解其核心概念,通过实践来学习和掌握,你可以充分利用Spring框架的强大功能,提高你的开发效率和代码质量。
56 20
|
26天前
|
前端开发 Java Maven
Spring 和 Spring Boot 之间的比较
本文对比了标准Spring框架与Spring Boot的区别,重点分析两者在模块使用(如MVC、Security)上的差异。Spring提供全面的Java开发基础设施支持,包含依赖注入和多种开箱即用的模块;而Spring Boot作为Spring的扩展,通过自动配置、嵌入式服务器等功能简化开发流程。文章还探讨了两者的Maven依赖、Mvc配置、模板引擎配置、启动方式及打包部署等方面的异同,展示了Spring Boot如何通过减少样板代码和配置提升开发效率。总结指出,Spring Boot是Spring的增强版,使应用开发、测试与部署更加便捷高效。
205 11
|
1月前
|
消息中间件 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——发布/订阅消息的生产和消费
本文详细讲解了Spring Boot中ActiveMQ的发布/订阅消息机制,包括消息生产和消费的具体实现方式。生产端通过`sendMessage`方法发送订阅消息,消费端则需配置`application.yml`或自定义工厂以支持topic消息监听。为解决点对点与发布/订阅消息兼容问题,可通过设置`containerFactory`实现两者共存。最后,文章还提供了测试方法及总结,帮助读者掌握ActiveMQ在异步消息处理中的应用。
88 0
|
1月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
64 0
|
1月前
|
前端开发 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
65 0
|
1月前
|
Java 测试技术 微服务
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
32 0
|
1月前
|
SQL Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— application.yml 中对日志的配置
在 Spring Boot 项目中,`application.yml` 文件用于配置日志。通过 `logging.config` 指定日志配置文件(如 `logback.xml`),实现日志详细设置。`logging.level` 可定义包的日志输出级别,例如将 `com.itcodai.course03.dao` 包设为 `trace` 级别,便于开发时查看 SQL 操作。日志级别从高到低为 ERROR、WARN、INFO、DEBUG,生产环境建议调整为较高级别以减少日志量。本课程采用 yml 格式,因其层次清晰,但需注意格式要求。
126 0
|
1月前
|
缓存 NoSQL Java
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
163 79
下一篇
oss创建bucket