SpringBoot从入门到精通(二十七)JPA实现自定义查询,完全不需要写SQL!

简介: 前面讲了Spring Boot 整合Spring Boot JPA,实现JPA 的增、删、改、查的功能。JPA使用非常简单,只需继承JpaRepository ,无需任何数据访问层和sql语句即可实现完整的数据操作方法。 JPA除了这些功能和优势之外,还有非常强大的查询的功能。以前复查的查询都需要拼接很多查询条件,JPA 有非常方便和优雅的方式来解决

前面讲了Spring Boot 整合Spring Boot JPA,实现JPA 的增、删、改、查的功能。JPA使用非常简单,只需继承JpaRepository ,无需任何数据访问层和sql语句即可实现完整的数据操作方法。


JPA除了这些功能和优势之外,还有非常强大的查询的功能。以前复查的查询都需要拼接很多查询条件,JPA 有非常方便和优雅的方式来解决。Spring Data JPA 查询分为三种:

1、Spring Data JPA 默认实现的预定义的方法

2、需要根据查询的情况定义查询条件

3、通过@Query 注解,自定义hql 查询语句

接下来就聊一聊JPA 自定义查询,体验Spring Data JPA 的强大。


一、预定义查询

预定义方法就是我们上面看到的那些自带的方法,因为UserRepository继承了 JpaRepository 拥有了父类的这些JPA自带的方法。如下图所示:

image.png

我们看到,JpaRepository类默认自带了很多数据操作方法,包括save、delete、findAll、fidById、等方法。调用这些预定义的预定义方法也非常简单,具体如下所示:

@RequestMapping("/test")
public void test() {
    Users user = new Users();
    user.setId((long) 1);
    userRespository.findById((long) 1);
    userRespository.findAll();
    userRespository.delete(user);
    userRespository.deleteById((long) 1);
    userRespository.existsById((long) 1);
}

上面所有JpaRepository父类拥有的方法都可以直接调用 。


二、自定义查询

Spring Data JPA 支持根据实体的某个属性实现数据库操作,主要的语法是 findByXX、 readAByXX、queryByXX、 countByXX、 getByXX 后跟属性名称。

利用这个功能仅需要在定义的 Repository 中添加对应的方法名即可,无需具体实现完整的方法,使用时 Spring Boot 会自动动帮我们实现对应的sql语句。


1、属性查询

根据姓名查询,示例如下:

@Repository
public interface UserRespository extends JpaRepository<Users, Long> {
    Users findByName(String name,String account);
}

上面的实例可以看到,我们可以在UserRepository 接口中进行接口声明。例如,如果想根据实体的 name和account 这两个属性来进行查询User的信息。那么直接在 UserRepository 中增加一个接口声明即可。


2、组合条件查询

JPA不仅支持单个属性查询,还能支持多个属性,根据And、or 等关键字组合查询:

Users findByNameAndAccount(String name,String account);

上面的例子,就是根据姓名和账号两个条件组合查询。这个是组合查询的例子,删除和统计也是类似的:deleteByXXAndXX、countByXXAndXX。可以根据查询的条件不断地添加和拼接, Spring Boot 都可以正确解析和执行。


3、JPA关键字

JPA的自定义查询除了And、or 关键字外,基本上SQL语法中的关键字,JPA都支持,比如:like,between 等。

这个语句结构可以用下面的表来说明:

示例方法

JPQL语句

And

findByLastnameAndFirstname

… where x.lastname = ?1 and x.firstname = ?2

Or

findByLastnameOrFirstname

… where x.lastname = ?1 or x.firstname = ?2

Is,Equals

findByFirstname,findByFirstnameIs,findByFirstnameEquals

… where x.firstname = ?1

Between

findByStartDateBetween

… where x.startDate between ?1 and ?2

LessThan

findByAgeLessThan

… where x.age < ?1

LessThanEqual

findByAgeLessThanEqual

… where x.age <= ?1

GreaterThan

findByAgeGreaterThan

… where x.age > ?1

GreaterThanEqual

findByAgeGreaterThanEqual

… where x.age >= ?1

After

findByStartDateAfter

… where x.startDate > ?1

Before

findByStartDateBefore

… where x.startDate < ?1

IsNull

findByAgeIsNull

… where x.age is null

IsNotNull,NotNull

findByAge(Is)NotNull

… where x.age not null

Like

findByFirstnameLike

… where x.firstname like ?1

NotLike

findByFirstnameNotLike

… where x.firstname not like ?1



三、自定义SQL语句

上面介绍了JPA的很多条件查询的方法。但是,实际项目中,还是有些场景上面的查询条件无法满足。那么我们就可以通过 @Query 注解写hql 来实现。

@Query("select u from Users u where u.name = :name1")
List<UserDO> findByHql(@Param("name1") String name1);

说明:

  1、@Query 注解,表示用执行hql语句。

  2、name1等参数对应定义的参数。

上面是通过hql,如果hql 写着不习惯,也可以用本地 SQL 语句来完成查询:

@Query(value = "select * from users where name = ?1",nativeQuery = true)
List<User> findUserBySql(String name);

上面示例中的 ?1 表示方法参数中的顺序,nativeQuery = true 表示执行原生sql语句。


四、已命名查询

除了使用 @Query注解外,还可以使用@NamedQuery@NameQueries等注解定义命名查询。JPA的命名查询实际上就是给SQL查询语句起一个名字,执行查询时就是直接使用起的名字,避免重复写JPQL语句,使得查询方法能够复用。下面通过示例程序演示JPA已命名查询。


1. 定义命名查询

在实体类中,@NamedQuery注解定义一个命名查询语句,示例代码如下:

@Entity
@Table(name="t_user")
@NamedQuery(name="findAllUser",query="SELECT u FROM User u")
public class User {
    // Entity实体类相关定义
}

在上面的示例中,@NamedQuery中的name属性指定命名查询的名称,query属性指定命名查询的语句。如果要定义多个命名查询方法,则需要使用@NamedQueries注解:

@Entity
@Table(name="users")
@NamedQueries({
    @NamedQuery(name="findAllUser",query="SELECT u FROM User u"),
    @NamedQuery(name="findUserWithId",query="SELECT u FROM User u WHERE u.id = ?1"),
    @NamedQuery(name="findUserWithName",query="SELECT u FROM User u WHERE u.name = :name")
})
public class User {
    // Entity实体类相关定义
}

在上面的示例中,在User实体类中定义了findAllUser()findUserWithId()findUserWithName()三种方法。


2. 调用命名查询

定义命名查询后,可以使用EntityManager类中的createNamedQuery()方法传入命名查询的名称来创建查询:

@Resource
EntityManagerFactory emf;
@Test
public void testNamedQuery() {
   EntityManager em = emf.createEntityManager();
    Query query = em.createNamedQuery("findUserWithName");// 根据User实体中定义的命名查询
   query.setParameter("name", "weiz");
   List<User> users = query.getResultList();
    for (User u : users){
       System.out.println("name:"+u.getName()+",age:"+u.getAge());
    }
}

在上面的示例中,使用createNamedQuery创建对应的查询,JPA会先根据传入的查询名查找对应的NamedQuery,然后通过调用getResultList()方法执行查询并返回结果。


3. 运行验证

单击Run Test或在方法上右击,选择Run 'testNamedQuery',运行全部测试方法,结果如图9-7所示。定义的已命名查询findUserWithName的单元测试运行成功,并输出了相应的查询结果,说明使用JPA实现了自定义的已命名查询的功能。

image.png


最后

以上就把Spring Data JPA的查询功能介绍完了, JPA 简化了我们对数据库的操作,预定义很多常用的数据库方法,直接使用即可。另外 JPA 还有一个特点,就是不用关心数据库的表结构,需要更改的时候只需要修改对应 Model 的属性即可。




推荐阅读:

SpringBoot从入门到精通(二十六)超级简单的数据持久化框架!Spring Data JPA 的使用!

SpringBoot从入门到精通(二十五)搞懂自定义系统配置

SpringBoot从入门到精通(二十四)3分钟搞定Spring Boot 多环境配置!

SpringBoot从入门到精通(二十三)Mybatis系列之——实现Mybatis多数据源配置

SpringBoot从入门到精通(二十二)使用Swagger2优雅构建 RESTful API文档

SpringBoot从入门到精通(二十一)如何优雅的设计 RESTful API 接口版本号,实现 API 版本控制!

相关文章
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
1038 0
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
5月前
|
SQL 分布式计算 大数据
SparkSQL 入门指南:小白也能懂的大数据 SQL 处理神器
在大数据处理的领域,SparkSQL 是一种非常强大的工具,它可以让开发人员以 SQL 的方式处理和查询大规模数据集。SparkSQL 集成了 SQL 查询引擎和 Spark 的分布式计算引擎,使得我们可以在分布式环境下执行 SQL 查询,并能利用 Spark 的强大计算能力进行数据分析。
|
7月前
|
Java API 数据库
JPA简介:Spring Boot环境下的实践指南
上述内容仅是JPA在Spring Boot环境下使用的冰山一角,实际的实践中你会发现更深更广的应用。总而言之,只要掌握了JPA的规则,你就可以借助Spring Boot无比丰富的功能,娴熟地驾驶这台高性能的跑车,在属于你的程序世界里驰骋。
298 15
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
1177 2
|
11月前
|
Java Maven 开发者
编写SpringBoot的自定义starter包
通过本文的介绍,我们详细讲解了如何创建一个Spring Boot自定义Starter包,包括自动配置类、配置属性类、`spring.factories`文件的创建和配置。通过自定义Starter,可以有效地复用公共配置和组件,提高开发效率。希望本文能帮助您更好地理解和应用Spring Boot自定义Starter,在实际项目中灵活使用这一强大的功能。
974 17
|
9月前
|
SQL Java 编译器
深入理解 Spring Data JPA 的导入与使用:以 UserRepository为例
本文深入解析了 Spring Data JPA 中 `UserRepository` 的导入与使用。通过示例代码,详细说明了为何需要导入 `User` 实体类、`JpaRepository` 接口及 `@Repository` 注解。这些导入语句分别用于定义操作实体、提供数据库交互方法和标识数据访问组件。文章还探讨了未导入时的编译问题,并展示了实际应用场景,如用户保存、查询与删除操作。合理使用导入语句,可让代码更简洁高效,充分发挥 Spring Data JPA 的优势。
588 0
|
SQL 存储 机器学习/深度学习
如何让SQL速度飞起来 入门YashanDB优化器
优化器,SQL引擎的核心组成部分,是数据库中用于把关系表达式转换成最优执行计划的核心组件,影响数据库系统执行性能的关键组件之一。
164 15
|
10月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——拦截自定义异常
本文介绍了在实际项目中如何拦截自定义异常。首先,通过定义异常信息枚举类 `BusinessMsgEnum`,统一管理业务异常的代码和消息。接着,创建自定义业务异常类 `BusinessErrorException`,并在其构造方法中传入枚举类以实现异常信息的封装。最后,利用 `GlobalExceptionHandler` 拦截并处理自定义异常,返回标准的 JSON 响应格式。文章还提供了示例代码和测试方法,展示了全局异常处理在 Spring Boot 项目中的应用价值。
528 0
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
2219 15