【Spring Boot】JPA 的查询方式

JPA 的查询方式

  • 1.使用约定方法名
  • 2.用 JPQL 进行查询
  • 3.用原生 SQL 进行查询
    • 3.1 根据 ID 查询用户
    • 3.2 查询所有用户
    • 3.3 根据 email 查询用户
    • 3.4 根据 name 查询用户,并返回分页对象 Page
    • 3.5 根据名字来修改 email 的值
    • 3.6 使用事务
  • 4.用 Specifications 进行查询
  • 5.用 ExampleMatcher 进行查询
  • 6.用谓语 QueryDSL 进行查询
  • 7.用 NamedQuery 进行查询

1.使用约定方法名

约定方法名一定要根据命名规范来写,Spring Data 会根据前缀、中间连接词(OrAndLikeNotNull 等类似 SQL 中的关键词)、内部拼接 SQL 代理生成方法的实现。

约定方法名的方法见下表(不完全示例):

SQL
方法例子
JPQL 语句
andfindByLastnameAndFirstnamewhere x.lastname = ?1 and x.firstname = ?2
orfindByLastnameOrFirstnamewhere x.lastname = ?1 or x.firstname = ?2
=findByFirstname / findByFirstnameIs / findByFirstnameEqualswhere x.firstname = ?1

接口方法的命名规则也很简单,只要明白 AndOrIsEqualGreaterStartingWith 等英文单词的含义,就可以写接口方法。具体用法如下:

public interface UserRepository extends Repository<User, Long> {
    List<User> findByEmailOrName(String email, String name);
}

上述代码表示,通过 emailname 来查找 User 对象。

约定方法名还可以支持以下几种语法:

  • User findFirstByOrderByNameAsc()
  • Page<User> queryFirst100ByName(String name, Pageable pageable)
  • Slice<User> findTop100ByName(String name, Pageable pageable)
  • List<User> findFirst100ByName(String name, Sort sort)
  • List<User> findTop100ByName(String name, Pageable pageable)

2.用 JPQL 进行查询

JPQL 语言(Java Persistence Query Language)是一种和 SQL 非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的 SQL 语言,从而屏蔽不同数据库的差异。

JPQL 语言通过 Query 接口封装执行,Query 接口封装了执行数据库查询的相关方法。调用 EntityManager 的 Query、NamedQuery 及 NativeQuery 方法可以获得查询对象,进而可调用 Query 接口的相关方法来执行查询操作。

JPQL 是面向对象进行查询的语言,可以通过自定义的 JPQL 完成 UPDATE 和 DELETE 操作。JPQL 不支持使用 INSERT。对于 UPDATE 或 DELETE 操作,必须使用注解 @Modifying 进行修饰。

JPQL 的用法见以下两段代码。

(1)下面代码表示根据 name 值进行查找。

public interface UserRepository extends JpaRepository<User, Long> (
  @Query("select u from User u where u.name = ?1")
  User findByName(String name);
}

(2)下面代码表示根据 name 值进行模糊查找。

public interface UserRepository extends JpaRepository<User, Long> { 
	@Query("select u from User u where u.name like %?1")
	List<User> findByName(String name);
}

3.用原生 SQL 进行查询

在使用原生 SQL 查询时,也使用注解 @Query。此时,nativeQuery 参数需要设置为 true。 下面先看一些简单的查询代码。

3.1 根据 ID 查询用户

public interface UserRepository extends JpaRepository<User, Long> (
	// 根据 ID 查询用户
	@Query(value = "select * from user u where u.id=:id", nativeQuery = true)
	User findById(@Param("id")Long id);
)

3.2 查询所有用户

public interface UserRepository extends JpaRepository<User, Long> {
	// 查询所有用户
	@Query(value = "select * from user", nativeQuery = true)
	List<User> findAllNative();
}

3.3 根据 email 查询用户

public interface UserRepository extends JpaRepository<User, Long> (
	// 根据 email 查询用户
	@Query(value = "select * from user where email= ?1", nativeQuery = true) 
	User findByEmail(String email);
)

3.4 根据 name 查询用户,并返回分页对象 Page

public interface UserRepository extends JpaRepository<User, Long> (
	@Query(value = "select * from user where name= ?1",
		   countQuery = "select count(*) from user where name= ?1", nativeQuery = true)
	Page<User> findByName(String name, Pageable pageable);
}

3.5 根据名字来修改 email 的值

@Modifying 
@Query("update user set email = :email where name =:name")
Void updateUserEmailByName(@Param("name")String name, @Param("email")String email);

3.6 使用事务

UPDATE 或 DELETE 操作需要使用事务。此时需要先定义 Service 层,然后在 Service 层的方法上添加事务操作。

对于自定义的方法,如果需要改变 Spring Data 提供的事务默认方式,则可以在方法上使用注解 @Transactional,如以下代码:

@Service
public classUserService {
  @Autowired
  private UserRepository userRepository;
  @Transactional
  public void updateEmailByName(String name, String email) {
    userRepository.updateUserEmaiByName(name, email);
  }
)

测试代码:

@Test
public void testUsingModifingAnnotation() {
  userService.updateEmailByName("pipi", "88888888@qq.com");
}

在进行多个 Repository 操作时,也应该使这些操作在同一个事务中。按照分层架构的思想,这些操作属于业务逻辑层,因此需要在 Service 层实现对多个 Repository 的调用,并在相应的方法上声明事务。

4.用 Specifications 进行查询

如果要使 Repository 支持 Specification 查询,则需要在 Repository 中继承 JpaSpecificationExecutor 接口,具体使用见如下代码:

public interface CardRepository extends JpaRepository<Card,Long>, JpaSpecificationExecutor<Card> {
	Card findById(long id);
}

下面以一个例子来说明 Specifications 的具体用法:

@SpringBootTest
@RunWith(SpringRunner.class)
public class testJpaSpecificationExecutor (
  @Autowired
  private CardRepository cardRepository;
  @Test
  public void testJpaSpecificationExecutor() (
    int pageNo = 0;
    int pageSize = 5;
    PageRequest pageable = PageRequest.of(pageNo, pageSize);
    // 通常使用 Specification 的匿名内部类
    Specification<Card> specification = new Specification<Card>() {
        @Override
        public Predicate toPredicate(Root<Card> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
          Path path = root.get("id");
          // gt 是大于的意思。这里代表 id 大于 2
          Predicate predicate1 = cb.gt(path, 2);
          // equal 是等于的意思,代表查询 num 值为 422803 的数据记录
          Predicate predicate2 = cb.equal(root.get("num"), 422803);
          // 构建组合的 Predicate
          Predicate predicate = cb.and(predicate1, predicate2); 
          return predicate;
        }
    };
    Page<Card> page = cardRepository.findAll(specification, pageable);
    System.out.println("总记录数: " + page.getTotalElements());
    System.out.println("当前第: " + (page.getNumber() + 1) + "页");
    System.out.println("总页数: " + page.getTotalPages());
    System.out.println("当前页面的 List: " + page.getContent());
    System.out.println("当前页面的记录数: "+ page.getNumberOfElements());
  }
)

代码解释如下:

  • CriteriaQuery 接口:specific 的顶层查询对象,它包含查询的各个部分,比如,selectfromwheregroup byorder by 等。CriteriaQuery 对象只对实体类型或嵌入式类型的 Criteria 查询起作用。
  • root:代表查询的实体类是 Criteria 查询的根对象。Criteria 查询的根定义了实体类型,能为将来的导航获得想要的结果。它与 SQL 查询中的 From 子句类似。Root 实例是类型化的, 且规定了 From 子句中能够出现的类型。查询根实例通过传入一个实体类型给 AbstractQuery.from 方法获得。
  • query:可以从中得到 Root 对象,即告知 JPA Criteria 查询要查询哪一个实体类。还可以添加查询条件,并结合 EntityManager 对象得到最终查询的 TypedQuery 对象。
  • CriteriaBuilder 对象:用于创建 Criteria 相关对象的工厂,可以从中获取到 Predicate 对象。
  • Predicate 类型:代表一个查询条件。

运行上面的测试代码,在控制台会输出如下结果(确保数据库已经存在数据):

Hibernate: select card0_.id as id1_0_, card0_.num as num2_0_ from card cardO_ where card0_.id>2 and card0_.num=422803 limit ?
Hibernate: select count(card0_.id) as col_0_0_ from card card0_ where card0_.id>2 and card0_.num=422803
总记录数: 6
当前第: 1页 
总页数: 2 
当前页面的 List: [Card(id=4, num=422803), Card(id=8, num=422803), Card(id=10, num=422803), Card(id=20, num=422803), Card(id=23, num=422803)] 
当前页面的记录数: 5

5.用 ExampleMatcher 进行查询

Spring Data 可以通过 Example 对象来构造 JPQL 查询,具体用法见以下代码:

User user = new User();
//构建查询条件
user.setName("pipi")ExampleMatcher matcher = ExampleMatcher.matching()
	// 创建一个 ExampleMatcher, 不区分大小写匹配 name
	.withIgnorePaths("name")
	// 包括 null 值
	.withIncludeNullValues()
	// 执行后缀匹配
	.withStringMatcherEnding();
// 通过 Example 构建查询
Example<User> example = Example.of(user, matcher);
List<User> list = userRepository.findALL(example);

默认情况下,ExampleMatcher 会匹配所有字段。

可以指定单个属性的行为(如 name 或内嵌属性 name.user)。如:

  • withMatcher("name", endsWith())
  • withMatcher("name", startsWith().ignoreCase())

6.用谓语 QueryDSL 进行查询

QueryDSL 也是基于各种 ORM 之上的一个通用查询框架,它与 Spring Data JPA 是同级别的。使用 QueryDSL 的 API 可以写出 SQL 语句(Java 代码,非真正标准 SQL),不需要懂 SQL 语句。它能够构建类型安全的查询。这与 JPA 使用原生查询时有很大的不同,可以不必再对 Object[] 进行操作。它还可以和 JPA 联合使用。

7.用 NamedQuery 进行查询

官方不推荐使用 NamedQuery,因为它的代码必须写在实体类上面,这样不够独立。其使用方法见以下代码:

©Entity 
@NamedQuery(name = "User.findByName", query = "select u from User u where u.name = ?1") 
public class User {
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/767711.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《梦醒蝶飞:释放Excel函数与公式的力量》8.3 COUNTBLANK函数

8.3 COUNTBLANK函数 在数据处理和分析中&#xff0c;我们经常需要识别和统计数据集中的空白单元格。COUNTBLANK函数是Excel中用于统计某个范围内空白单元格数量的强大工具。 8.3.1 函数简介 COUNTBLANK函数用于统计指定范围内的空白单元格数量。这在数据清洗、数据完整性检查…

头条系统-05-延迟队列精准发布文章-概述添加任务(db和redis实现延迟任务)、取消拉取任务定时刷新(redis管道、分布式锁setNx)...

文章目录 延迟任务精准发布文章 1)文章定时发布2)延迟任务概述 2.1)什么是延迟任务2.2)技术对比 2.2.1)DelayQueue2.2.2)RabbitMQ实现延迟任务2.2.3)redis实现 3)redis实现延迟任务4)延迟任务服务实现 4.1)搭建heima-leadnews-schedule模块4.2)数据库准备4.3)安装redis4.4)项目…

【OpenSSH】立即检测 OpenSSH 的 regreSSHion 漏洞

OpenSSH regreSSHion 漏洞简介 OpenSSH 是一种广泛使用的网络协议&#xff0c;提供加密的数据通信和远程登录功能。然而&#xff0c;最近发现的一个漏洞&#xff08;CVE-2024-6387&#xff09;&#xff0c;被称为 regreSSHion&#xff0c;使得未经身份验证的攻击者能够在 Linu…

Android触摸事件分发关键点【笔记摘要】

触摸事件分发&#xff1a;就是一个为了解决触摸事件冲突而设置的机制 1.事件类型 ACTION_DOWN -> ACTION_UP / ACTION_CANCEL ACTION_DOWN -> ACTION_MOVE -> ACTION_MOVE -> ACTION_MOVE -> ACTION_UP / ACTION_CANCEL 这个取消事件ACTION_CANCEL它是一种特殊…

基于物品的协同过滤算法

预估用过户对候选物品的兴趣 计算物品相似度 召回通道 快速做召回条件

iPhone苹果手机怎么取消腾讯视频VIP会员自动续费?

腾讯视频会员分为VIP&#xff08;同时在线设备5台、同时播放设备2台&#xff1b;&#xff09;和SVIP&#xff08;同时在线设备8台、同时播放设备3台&#xff1b;&#xff09;&#xff0c;在iPhone苹果手机上开通腾讯视频连续包月、包季、包年后&#xff0c;需要手动取消才能关闭…

UE4_材质_材质节点_DepthFade

一、DepthFade参数 DepthFade&#xff08;深度消退&#xff09;表达式用来隐藏半透明对象与不透明对象相交时出现的不美观接缝。 项目说明属性消退距离&#xff08;Fade Distance&#xff09;这是应该发生消退的全局空间距离。未连接 FadeDistance&#xff08;FadeDistance&a…

被⽹络罪犯利⽤的5⼤ChatGPT越狱提⽰

⾃ChatGPT发布的近18个月以来&#xff0c;⽹络罪犯们已经能够利⽤⽣成式AI进⾏攻击。OpenAI在其内容政策中制定了限制措施&#xff0c;以阻⽌⽣成恶意内容。作为回应&#xff0c;攻击者们创建了⾃⼰的⽣成式AI平台&#xff0c;如 WormGPT和FraudGPT&#xff0c;并且他们还分享了…

Ubuntu22.04上Docker的安装

1. 使用APT安装 首先安装HTTPS传输的软件包和CA证书&#xff0c;确保软件下载过程中不被篡改。 sudo apt-get updatesudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release -y然后&#xff0c;使用国内源&#xff0c;并添加软件源的 GPG 密钥以防…

删除keil!VSvode+eide+jlink(stlink)配置keil工程,调试使用cortex-debug+openocd

文章目录 目的前期准备1.软件安装2.VScode安装3.VScode插件安装4.安装ARM-GCC交叉编译器 工程导入程序编译jlink在线调试部分常见问题更改为GCC 编译器更改为stlinkopencd一些tips调试变量查看构建器选项配置 目的 提示&#xff1a;这里可以添加技术概要 vscode代替keil进行程…

Ozon、美客多补单测评黑科技:打造无懈可击的自养号补单环境

不管哪个跨境平台的风控都会做升级&#xff0c;相对的补单技术也需要进行相应的做升级&#xff0c;风控升级后&#xff0c;自己养号补单需要注意以下技术问题&#xff0c;以确保补单的稳定性和安全性&#xff1a; 一、物理环境 1. 硬件参数伪装&#xff1a;平台已经开始通过I…

择校秘籍:如何找到口碑爆棚的学校?以星贝育园为例

在为孩子选择学校时&#xff0c;家长们总是慎之又慎&#xff0c;希望能找到一所口碑好、教育质量高的学校&#xff0c;为孩子的未来奠定坚实的基础。今天&#xff0c;我们就以星贝育园为例&#xff0c;来探讨一下如何选择口碑好的学校。 一、考察师资力量 优秀的教师团队是一所…

什么是定时器?

前言&#x1f440;~ 上一章我们介绍了阻塞队列以及生产者消息模式&#xff0c;今天我们来讲讲定时器 定时器 标准库中的定时器 schedule()方法 扫描线程 手动实现定时器 任务类 存储任务的数据结构 定时器类 如果各位对文章的内容感兴趣的话&#xff0c;请点点小赞&am…

帮找Java Bug,面试,项目,解决Java问题

本人是个Java老程序员&#xff0c;如果你有解决不了的问题&#xff0c;或者面试的时候需要人帮助&#xff0c;或者求职就业上任何问题都可以联系我&#xff0c;下面是我微信&#xff0c;欢迎联系我&#xff01;

【JUC】可重入锁理解

可重入锁&#xff08;Reentrant Lock&#xff09;&#xff0c;也称作递归锁&#xff0c;是一种特殊的锁机制&#xff0c;它允许同一个线程多次获取同一个锁。 优点是可以避免死锁。 public class WhatReentrant {public static void main(String[] args) {new Thread(new Runn…

Qt——升级系列(Level Eight):界面优化

目录 QSS 背景介绍 基本语法 QSS设置方式 指定控件样式设置 全局样式设置 从文件加载样式表 使用Qt Designer 编辑样式 选择器 选择器概况 子控件选择器 伪类选择器 样式属性 盒模型 控件样式示例 按钮 复选框、单选框 输入框 列表 菜单栏 登录界面 绘图 基本概念 绘制各种形…

【Kali-linux for WSL】图形化界面安装

文章目录 前言图形化界面安装 前言 之前在WSL中安装了Kali 启动之后发现什么都没有&#xff01;&#xff01;&#xff01; 那我还怎么学习渗透技术&#xff1f;&#xff1f;&#xff1f; 看来&#xff0c;得改进下我的kali-linux for wsl&#xff0c;安装个图形化界面 图形化…

Jetson系列机载电脑创建热点模式配置方法

Jetson nano为例—— 创建热点模式配置方法 1.1、新建一个 WiFi 在屏幕右上角找到网络图标&#xff0c;点击后选择“Edit Connections”选项&#xff0c;进入选择网络连接页面&#xff0c;然后点击左下角加号&#xff0c;新建一个连接&#xff0c;类型选择 WiFi 后点击 “cre…

AI降重,不再难:降AI率的实用技巧大揭秘

如何有效降低AIGC论文的重复率&#xff0c;也就是我们说的aigc如何降重&#xff1f;AIGC疑似度过高确实是个比较愁人的问题。如果你用AI帮忙写了论文&#xff0c;就一定要在交稿之前做一下AIGC降重的检查。一般来说&#xff0c;如果论文的AIGC超过30%&#xff0c;很可能会被判定…

剪画小程序:如何将视频变成自己的作品!在手机上这样做就可以了!

亲爱的小伙伴们&#xff0c;我是你们的博主小画&#xff01; 今天和大家分享两个在视频剪辑中实用的技巧—旋转视频和添加水印&#xff01; 在我们的创作过程中&#xff0c;有时候常规的视角并不能完全展现出视频的魅力和创意。而通过旋转视频&#xff0c;就能为观众带来全新的…