教程

使用 JUnit 和 @DataJpaTest 测试 Spring Data Repository

1、简介 在使用 Spring Data JPA 进行数据持久化的 Spring Boot 应用中,测试与数据库交互的 Repository 至关重要。 本文将带你了解如何使用 Spring Boot 提供的 @DataJpaTest 注解和 JUnit 对 Spring Data JPA Repository 进行有效地测试。 2、了解 @DataJpaTest 和 Repository 类 本节主要介绍在 Spring Boot 应用中,@DataJpaTest 和 Repository 之间的交互。 2.1、@DataJpaTest @DataJpaTest 注解用于测试 Spring Boot 应用中的 JPA Repository。它是一个专门的测试注解,为测试持久层提供了一个最小的 Spring Context。该注解可与 @RunWith 和 @SpringBootTest 等其他测试注解结合使用。 此外,@DataJpaTest 的范围仅限于应用的 JPA Repository 层。它不会加载整个 Application Context,从而使测试更快、更集中。此注解还为测试 JPA 实体提供了预配置的 EntityManager 和 TestEntityManager。 2.2、Repository 在 Spring Data JPA 中,Repository 是 JPA 实体之上的一个抽象层。它为执行 CRUD(创建、读取、更新、删除)操作和执行自定义查询提供了一组方法。这些 Repository 通常从 JpaRepository 等接口继承而来,负责处理与特定实体类型相关的数据库交互。

Spring Data JPA 执行 INSERT 时跳过 SELECT

1、概览 在某些情况下,当使用 Spring Data JPA Repository 保存实体时,可能会在日志中遇到额外的 SELECT。这可能会因大量额外调用而导致性能问题。 本文将带你了解如何在 Spring Data JPA 中执行 INSERT 时跳过 SELECT,以提高性能。 2、设置 在深入 Spring Data JPA 并对其进行测试之前,先要做一些准备工作。 2.1、依赖 为了创建测试 Repository,需要使用 Spring Data JPA 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> 使用 H2 数据库作为测试数据库: <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> 使用 Spring Context 进行集成测试。添加 spring-boot-starter-test 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> 2.2、配置 本例中使用的 JPA 配置如下: spring.jpa.hibernate.dialect=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.hibernate.show_sql=true spring.jpa.hibernate.hbm2ddl.auto=create-drop 如上,让 Hibernate 生成 schema,并将所有 SQL 查询记录到日志中。 3、导致 SELECT 查询的原因 首先,创建一个 Task 实体:

Spring Data JPA Repository 和数据库视图

1、概览 数据库视图(Database View)是关系型数据库系统中的一种类似表的结构,其中的数据源来自一个或多个连接在一起的表。 Spring Data Repository 通常用于数据库表,但也可以有效地应用于数据库视图。本文将带你了解如何在 Spring Data JPA 中使用 Repository 从数据库视图检索数据。 2、数据库表设置 本文使用 H2 数据库系统进行数据定义,并使用 SHOP 和 SHOP_TRANSACTION 这两个示例表演示数据库视图概念。 SHOP 表存储商店信息: CREATE TABLE SHOP ( shop_id int AUTO_INCREMENT, shop_location varchar(100) NOT NULL UNIQUE, PRIMARY KEY(shop_id) ); SHOP_TRANSACTION 表存储与商店相关的交易记录,并通过 shop_id 对 SHOP 表进行引用: CREATE TABLE SHOP_TRANSACTION ( transaction_id bigint AUTO_INCREMENT, transaction_date date NOT NULL, shop_id int NOT NULL, amount decimal(8,2) NOT NULL, PRIMARY KEY(transaction_id), FOREIGN KEY(shop_id) REFERENCES SHOP(shop_id) ); 在实体-关系(ER)模型中,可以将其说明为 “一对多” 的关系,即一个商店可以有多笔交易。但是,每笔交易只与一家商店相关联。可以用 ER 图直观地表示这一点:

Spring Data Jpa 中的 Query Hint

1、简介 本文将带你了解 Spring Data JPA 中 Query Hint (查询提示)的功能、基本原理以及如何有效地应用它们。 这些提示有助于优化数据库查询,并通过影响优化器的决策过程来改善应用性能。 2、理解 Query Hint Spring Data JPA 中的 Query Hint 是一种强大的工具,可帮助优化数据库查询并提高应用性能。与直接控制执行不同,Query Hint 会影响优化器(Optimizer)的决策过程。 在 Spring Data JPA 中,可以在 org.hibernate.annotations 包中找到这些 Hint,同时还有与 Hibernate 相关的各种注解和类。需要注意的是,这些 Hint 的解释和执行通常取决于底层持久化层实现(Persistence Provider),如 Hibernate 或 EclipseLink,因此它们是特定于厂商的。 3、使用 Query Hint Spring Data JPA 提供了多种利用 Query Hint 优化数据库查询的方法。 3.1、基于注解的配置 Spring Data JPA 提供了一种使用注解为 JPA 查询添加 Query Hint 的简便方法。通过 @QueryHints 注解,可以指定用于生成 SQL 查询的 JPA @QueryHint 数组。 示例如下,设置了 JDBC fetch size Hint,以限制结果返回的大小:

在 Spring Boot 中使用 JPA 调用自定义数据库函数

1、概览 数据库函数是数据库管理系统的重要组成部分,可将逻辑和执行封装在数据库中。它们有助于高效的数据处理和操作。 本文将带你了解在 Spring Boot 应用中使用 Spring Data JPA 调用自定义数据库函数的各种方法。 2、项目设置 为了简单,本文使用 H2 数据库。 首先在 pom.xml 中加入 Spring Boot Data JPA 和 H2 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>3.2.2</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.2.224</version> </dependency> 3、数据库函数 数据库函数是通过在数据库中执行一组 SQL 语句或操作来执行特定任务的数据库对象。当逻辑是数据密集型的时候,这可以提高性能。虽然数据库函数和存储过程的操作类似,但它们也有不同之处。 3.1、函数与存储过程 虽然不同的数据库系统之间可能会有具体的差异,但它们之间的主要差异可归纳在下表中: 特点 数据库函数 存储过程 执行 可在查询中调用 必须明确调用 返回值 始终返回一个值 可返回无值、单值或多值 参数 仅支持输入参数 支持输入和输出参数 调用 无法使用函数调用存储过程 可使用存储过程调用函数 用途 通常执行计算或数据转换 通常用于复杂的业务逻辑 3.2、H2 函数 为了说明如何从 JPA 调用数据库函数,我们将创建一个在 H2 数据库中的数据库函数来说明如何从 JPA 中调用它。 H2 数据库函数只是一个嵌入的 Java 源代码,它将被编译和执行:

Spring Data JPA 使用 findby 定义多个条件列

1、简介 Spring Data JPA 提供了查询推导功能(派生查询),只需遵循方法名称约定就能自动推导出查询。 本文将带你了解如何使用查询推到功能,通过一列或多列查找实体。 2、设置 定义一个 Account 实体,其中包含与用户账户相关的属性: @Entity @Table(name = "ACCOUNTS") public class Account { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accounts_seq") @SequenceGenerator(name = "accounts_seq", sequenceName = "accounts_seq", allocationSize = 1) @Column(name = "user_id") private int userId; private String username; private String password; private String email; private Timestamp createdOn; private Timestamp lastLogin; @OneToOne @JoinColumn(name = "permissions_id") private Permission permission; // getter / setter } 为了演示,在 ACCOUNTS 表中添加一些示例数据:

Jackson 从类创建 JavaType

1、简介 使用 Jackson 时,或多或少都会遇到需要从给定的类(Class)对象中生成 JavaType 的情况。 本文将带你了解如何借助 Jackson 库从类创建 JavaType。 2、JavaType 和 Class 在了解详情之前,先来了解一下 JavaType 和 Class。 2.1、Java 中的 JavaType 在 Jackson 中,JavaType 类代表 Java 类型。它是一种机制,可以处理泛型和数组等通用类型。 创建 JavaType 实例非常重要,尤其是当我们在处理 JSON 时处理泛型结构。 2.2、Java 中的 Class 在 Java 中,Class 类是反射 API 的成员,在运行时用来表示类或接口。 此外,它还提供类的信息,包括名称、字段、方法和构造函数。 3、使用 TypeFactory 创建 JavaType 要使用 Jackson 从提供的 Class 对象生成 JavaType 实例,需要利用 TypeFactory 类。 TypeFactory 提供了一个默认实例,可以构建不同的类型,无论是泛型还是参数化类型。 以使用 TypeFactory 从泛型类生成 JavaType 对象为例: class MyGenericClass<T> { // Class 实现 } @Test void givenGenericClass_whenCreatingJavaType_thenJavaTypeNotNull() { Class<?

Spring Cloud AWS SQS v3 中的消息确认

1、概览 消息确认是 MQ 系统中的一种标准机制,它向 Message Broker 发出信号,表明消息已被消费,不应再次传递。在亚马逊的 SQS(Simple Queue Servic)中,确认是通过删除队列中的信息来执行的。 本文将带你了解 Spring Cloud AWS SQS v3 中开箱即提供的三种确认模式: ON_SUCCESS、MANUAL 和 ALWAYS。 本文将利用 Spring Cloud AWS SQS V3 入门文章 中的环境和测试设置,使用事件驱动场景来说明用例。 2、依赖 首先,导入 Spring Cloud AWS BOM,以确保 pom.xml 中的所有依赖项相互兼容: <dependencyManagement> <dependencies> <dependency> <groupId>io.awspring.cloud</groupId> <artifactId>spring-cloud-aws</artifactId> <version>3.1.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 还要添加 Core 和 SQS starter 依赖: <dependency> <groupId>io.awspring.cloud</groupId> <artifactId>spring-cloud-aws-starter-sqs</artifactId> </dependency> <dependency> <groupId>io.awspring.cloud</groupId> <artifactId>spring-cloud-aws-starter</artifactId> </dependency> 最后,添加测试所需的依赖,即带有 JUnit 5 的 LocalStack 和 TestContainers、用于验证异步消息消费的 awaitility 库,以及用于处理断言的 AssertJ:

Spring Cloud AWS 3.0 简介 - SQS 整合

1、概览 Spring Cloud AWS 是一个旨在简化与 AWS 服务交互的项目。SQS(Simple Queue Service)是 AWS 的一种解决方案,用于以可扩展的方式发送和接收异步消息。 本文将带你了解针对于 Spring Cloud AWS 3.0 完全重写的 Spring Cloud AWS SQS Integration。 该框架为处理 SQS 队列提供了熟悉的 Spring 抽象,如 SqsTemplate 和 @SqsListener 注解。 本文以一个事件驱动的场景为例,介绍了如何发送和接收消息。并展示使用 Testcontainers(一种管理一次性 Docker 容器的工具)和 LocalStack(可在本地模拟类似 AWS 的环境,用于测试)设置集成测试的策略。 2、依赖 Spring Cloud AWS BOM 可确保项目之间的版本兼容。它声明了包括 Spring Boot 在内的许多依赖项的版本。 添加 Spring Cloud AWS BOM 到 pom.xml: <dependencyManagement> <dependencies> <dependency> <groupId>io.awspring.cloud</groupId> <artifactId>spring-cloud-aws</artifactId> <version>3.0.4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 我们需要的主要依赖关系是 SQS Starter,它包含项目中所有与 SQS 相关的类。SQS Integration 不依赖于 Spring Boot,可在任何标准 Java 应用中独立使用:

在 Kubernetes 上实现 Spring Boot SSL 热重载

本文将带你了解如何为在 Kubernetes 上运行的 Spring Boot 应用配置 SSL 证书的热重载。我们将使用 Spring Boot 3.1 和 3.2 版本中引入的两个功能。第一个功能允许我们利用 SSL Bundle 在服务器端和客户端配置和使用自定义 SSL 配置。第二个功能使得在 Spring Boot 应用的嵌入式 Web 服务器中轻松进行 SSL 证书和密钥的热重载。 为了在 Kubernetes 上生成 SSL 证书,我们将使用 cert-manager。“cert-manager” 可以在指定期限后轮换证书,并将其保存为 Kubernetes Secret。之前的文章中介绍了如何在 Secret 更新时自动重启 Pod 的类似方案。我们使用 Stakater Reloader 工具在新版本的 Secret 上自动重启 pod。不过,这次我们使用 Spring Boot 新特性来避免重新启动应用(Pod)。 源码 你也可以克隆我的源代码,亲自尝试一下。首先克隆我的 GitHub 仓库。然后切换到 ssl 目录。你会发现两个 Spring Boot 应用:secure-callme-bundle 和 secure-caller-bundle。之后,你只需按照说明操作即可。 工作原理 在介绍技术细节之前,首先来了解我们的应用架构和面临的挑战。我们需要设计一个解决方案,在 Kubernetes 上运行的服务之间实现 SSL/TLS 通信。这个解决方案必须考虑到证书重载的情况。此外,服务器和客户端必须同时进行重载,以避免通信中出现错误。在服务器端,使用嵌入式 Tomcat 服务器。在客户端应用中,使用 Spring RestTemplate 对象。