Jakarta Persistence 3.2 简介

1、简介 Jakarta Persistence(前身为 JPA)是 Java 中对象关系映射的标准 API。它使开发人员能够在 Java 应用中管理关系数据,并通过使用注解和实体类将 Java 对象映射到数据库表来简化数据库交互。 本文将带你了解 Jakarta Persistence 3.2 中引入的一些关键新功能,重点介绍在配置、性能和可用性方面的改进。 2、Jakarta Persistence 3.2 是什么? Jakarta Persistence 3.2 是 Jakarta Persistence API 的最新版本,它为 Java 应用中的对象关系映射(ORM)提供了一种标准化方法。 该版本改进了查询功能、性能和可用性,并增强了对现代数据库功能的支持。 要添加对 Jakarta Persistence 3.2 的支持,必须在 pom.xml 中添加以下 Maven 依赖: <dependency> <groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> <version>3.2.0</version> </dependency> 此外,还需要支持该 API 的最新 Hibernate 7 版本: <dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-core</artifactId> <version>7.0.0.Beta1</version> </dependency> 3、关键的新功能 Jakarta Persistence 3.2 引入了一些新功能,以改进数据库连接处理、模式配置和事务管理。 3.1、持久化配置 最新的 Jakarta Persistence 3.2 版本添加了编程式 API,可使用 PersistenceConfiguration 类而不是传统的 persistence.

将 OpenAPI 2.0 规范转换为 OpenAPI 3.0

1、简介 尽管 OpenAPI 3.x 规范自 2017 年起就已发布,并经历了多次更新,但目前许多 API 仍在继续使用旧版本。 本文将带你了解 OpenAPI 2.0 和 OpenAPI 3.0 规范之间的主要区别,以及如何将 OpenAPI 2.0 规范转换为 OpenAPI 3.0。 2、OpenAPI 2.0 和 OpenAPI 3.0 简单回顾一下,OpenAPI 提供了一种标准格式,用于描述人类和机器都能读懂的 HTTP API。在 3.0 版之前,OpenAPI 被称为 Swagger 规范和 Swagger 工具包的一部分。从那时起,它已成为行业标准,并经过多次更新,带来了更多改进和功能。 与 2.0 相比,OpenAPI 3.0 引入了几项根本性变化。 首先,对整体结构进行了重构,以提高可重用性。添加了一个 components(组件)块来组织现有元素(如 schemas、responses、parameters)和新元素(请求 requestBody、examples 和 headers)。一些元素被重新命名 - definitions 现在被称为 schemas,securityDefinitions 被称为 securitySchemes。 此外,OpenAPI 3.0 还进一步扩展了 JSON Schema 功能。添加了 oneOf、anyOf 和 not 等关键字,以便对复杂的数据格式进行描述和灵活验证。 3.0 版本还引入了对 cookie 参数、内容类型协商和回调机制的支持。它还扩展了安全定义并简化了现有流程。 最后,你可以在官方 更新日志 中查看完整的变更列表。

使用 Java 通过 SSH 连接远程 MySQL 数据库

1、概览 Secure Shell(SSH)允许我们安全地访问和管理远程系统,包括执行命令、传输文件和隧道服务。 我们可以通过 SSH 会话建立与远程 MySQL 数据库的连接。Java 有多个 SSH 客户端,其中最常见的是 Java Secure Channel(JSch)。 本文将带你了解如何通过 SSH 会话连接到运行在远程服务器上的 MySQL 数据库。 2、了解 SSH 端口转发 端口转发允许通过在 SSH 连接上将流量从本地端口重定向到远程服务器上的端口,从而实现客户系统和远程服务器之间的数据传输。 当防火墙或其他限制阻止直接连接远程服务器的 IP 和端口时,这一点尤其有用。 在本例中,MySQL 服务器运行在远程服务器的 localhost 上,通常使用 3306 端口。虽然从技术上讲,可以直接连接到远程服务器的 IP 和 MySQL 端口,但出于安全考虑,这通常会受到限制(3306 端口未开放)。相反,我们可以通过 SSH 使用本地端口转发来建立与数据库的安全连接。 在本地端口转发中,我们在本地机器上分配一个可用端口,并将其与远程运行的 MySQL 服务器端口绑定,以允许我们的程序与远程服务器之间进行数据通信。 3、Maven 依赖 首先,在 pom.xml 中添加 JSch 和 MySQL 驱动依赖: <dependency> <groupId>com.github.mwiede</groupId> <artifactId>jsch</artifactId> <version>0.2.20</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>9.0.0</version> </dependency> JSch 提供了 Session 等类,这些类对于建立与远程服务器的 SSH 连接至关重要。此外,MySQL 驱动允许我们与运行中的 MySQL 服务器建立连接。

处理 MySQL 异常:“MysqlDataTruncation: Data truncation: Data too long for column”

1、概览 Java 数据库连接(JDBC)应用编程接口(API)提供了一系列类和接口。我们可以使用它们连接关系数据库等数据源并运行 SQL 语句。 以流行的 MYSQL 为例,当我们需要连接到 MySQL 时,就需要使用 MySQL 数据库的专用 JDBC 驱动程序: com.mysql.cj.jdbc.Driver,该驱动实现了 JDBC API。 在运行 SQL 语句时,我们可能会遇到异常:“com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Data too long for column”。 本文将带你了解出现此异常的原因,以及解决办法。 2、Schema 设置 首先,创建如下关系表 department: DESC department; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int | NO | PRI | NULL | | | name | varchar(50) | YES | | NULL | | | code | varchar(4) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 注意,code 列定义只允许使用大小为 4 或更小的 varchar。

使用 Bouncy Castle 签署 CSR

1、概览 签署(也叫做签发)证书签名请求(CSR)是密码学中的一项常见操作。本文将带你了解如何使用 Bouncy Castle 签署 CSR。 2、签署 CSR 签署 CSR 是证书颁发机构(CA)验证 CSR 中的信息并颁发证书的过程。CA 使用其私钥签署证书。签名后的证书可在客户端和服务器之间建立安全连接。 要使用 Bouncy Castle 签署 CSR,需要执行几个基本步骤: 生成可信实体 CA 证书和私钥。 生成证书签名请求(CSR)。 使用 CA 证书和私钥签署 CSR。 3、设置 首先,需要在 pom.xml 中添加 Bouncy Castle 依赖: <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk18on</artifactId> <version>1.76</version> </dependency> 接下来,需要创建一个 SecurityProvider 类来注册 Bouncy Castle Provider: static { Security.addProvider(new BouncyCastleProvider()); } 4、使用 Bouncy Castle 签署 CSR 使用 Bouncy Castle 签署 CSR 需要几个步骤。 4.1、生成可信实体 CA 证书和私钥 CA 是向客户签发证书的可信实体。我们必须生成 CA 证书和私钥来签署 CSR。 先生成一个密钥对:

Java 中 interface 和 @interface

1、概览 本文将带你了解 Java 中 interface(接口)和 @interface(注解接口)的区别以及它们的应用。 interface是一个类实现的规范。在最常见的形式中,它是一组相关方法,这些方法没有具体的实现。 而 @interface 则允许你在代码中添加元数据。编译器、工具或框架使用这些元数据来影响类的行为或处理过程。 2、interface interface 是一种规范。它规定了实现类必须实现的行为,但没有规定如何实现。它表明,任何实现接口的类都必须为接口的所有方法提供具体的实现。 public interface Animal { String eat(); String sleep(); } public class Dog implements Animal { @Override public String eat() { return "Dog is eating"; } @Override public String sleep() { return "Dog is sleeping"; } } 接口的所有方法都是默认 public 和 abstract 的(default 方法和 static 方法除外),所有字段都是 public、static 和 final 的。在 Java 中,我们可以使用接口实现抽象、多重继承和松散耦合。 抽象:接口只定义了调用方法所需的基本信息,而实现方法的复杂性则被隐藏起来。 多重继承:一个类可以实现多个接口,从而避免了在允许类多重继承的语言中可能出现的 “菱形继承” 问题。 松耦合:接口在功能和实现细节之间提供了明显的分离。由于我们对方法和签名进行了单独定义,它使一个类可以改变其内部流程,而不影响其用户。 3、@interface 在Java中,我们使用 @interface 来声明注解类型。注解提供了一种向 Java 代码元素(如类、方法和字段)添加元数据的方式。因此,工具和库可以利用这些元数据在编译过程或运行时收集信息,以进行代码处理。

Kafka 中的 InstanceAlreadyExistsException 异常

1、简介 Apache Kafka 是一个功能强大的分布式流平台,被广泛用于构建实时数据管道和流应用。然而,Kafka 在运行过程中可能会遇到各种异常和错误。其中一个常见的异常就是 InstanceAlreadyExistsException。 本文将带你了解 Kafka 出现 InstanceAlreadyExistsException 异常的原因和解决办法。 2、InstanceAlreadyExistsException 异常是什么? InstanceAlreadyExistsException 是 java.lang.RuntimeException 的子类。在 Kafka 的上下文中,这个异常通常在尝试创建具有与现有生产者或消费者相同的 Client ID 的 Kafka 生产者或消费者时出现。 每个 Kafka 客户端实例都有一个唯一的 Client ID,它对 Kafka 集群内的元数据跟踪和客户端连接管理至关重要。如果试图创建一个新的客户端实例,而 Client ID 已被现有客户端使用,Kafka 会抛出 InstanceAlreadyExistsException(实例已存在异常)。 3、内部机制 虽然我们提到 Kafka 会抛出这个异常,但值得注意的是,Kafka 通常会在其内部机制中优雅地处理这个异常。通过在内部处理异常,Kafka 可以将问题隔离和限制在其自身的子系统中。这可以防止异常影响主线程,并潜在地导致更广泛的系统不稳定或停机。 在 Kafka 的内部实现中,registerAppInfo() 方法通常在初始化 Kafka 客户端(生产者或消费者)时被调用。假设现有的客户端有相同的 client.id,该方法会捕获 InstanceAlreadyExistsException。由于异常是在内部处理的,它不会被抛到主线程上,而人们可能希望在主线程上捕获异常。 4、InstanceAlreadyExistsException 的原因 在本节中,我们将通过代码示例来研究导致 InstanceAlreadyExistsException 的各种情况。 4.1、消费者组中重复的 Client ID Kafka 规定同一消费者组内的消费者有不同的 Client ID。当一个组内的多个消费者共享相同的 Client ID 时,Kafka 的消息传递语义可能会变得不可预测。这会干扰 Kafka 管理偏移量和维护消息顺序的能力,可能导致消息重复或丢失。因此,当多个消费者共享同一个 Client ID 时,就会触发该异常。

使用 MongoDB 和 Spring AI 构建 RAG 应用

1、概览 AI(人工智能)技术的使用正成为现代开发中的一项关键技能。在本文中,我们将构建一个 RAG Wiki 应用,它可以根据存储的文档回答问题。 我们会通过 Spring AI 将应用与 MongoDB Vector 数据库 和 LLM 集成。 2、RAG 应用 当自然语言生成需要依赖上下文数据时,我们就会使用 RAG(Retrieval-Augmented Generation)应用。RAG 应用的一个关键组成部分是向量数据库(Vector Database),它在有效管理和检索这些数据方面起着至关重要的作用: 我们使用 Embedding Model 来处理源文件。Embedding Model 将文档中的文本转换为高维向量。这些向量捕捉了内容的语义,使我们能够根据上下文而不仅仅是关键词匹配来比较和检索类似的内容。然后,我们将文档存储到向量数据库。 保存文档后,我们可以通过以下方式发送提示信息: 首先,我们使用 Embedding Model 来处理问题,将其转换为捕捉其语义的向量。 接下来,进行相似性搜索,将问题的向量与存储在向量库中的文档向量进行比较。 从最相关的文档中,为问题建立一个上下文。 最后,将问题及其上下文发送给 LLM,LLM 会根据所提供的上下文构建与查询相关的回复。 3、MongoDB Atlas Search 在本教程中,我们将使用 MongoDB Atlas Search 作为我们的向量数据库。它提供的向量搜索功能可以满足我们在本项目中的需求。为了测试,我们使用 mongodb-atlas-local Docker 容器来设置 MongoDB Atlas Search 的本地实例。 创建一个 docker-compose.yml 文件: version: '3.1' services: my-mongodb: image: mongodb/mongodb-atlas-local:7.0.9 container_name: my-mongodb environment: - MONGODB_INITDB_ROOT_USERNAME=wikiuser - MONGODB_INITDB_ROOT_PASSWORD=password ports: - 27017:27017 4、依赖和配置 首先,添加必要的依赖项。由于我们的应用要提供 HTTP API,因此加入 spring-boot-starter-web 依赖:

Spring Boot v3.3.4 发布

Spring Boot v3.3.4 现已发布。 🐞 Bug 修复 当封装了 AbstractRoutingDataSource 时,management.health.db.ignore-routing-datasources=true 无效 #42322 OAuth2ClientProperties 验证错误信息中缺少详细信息 #42279 来自未使用的错误配置 SSL bundle 的 FileNotFoundException #42169 当 spring-web 不在 classpath 上时,ZipkinHttpClientSender 会出现 “Failed to introspect Class”(类自省失败)#42161 与容器 Bean 一起使用时,@RestartScope 可能会导致 “Recursive update(递归更新)”异常 #42107 JarLauncher 无法加载大型 jar 文件 #42079 PropertiesMigrationListener 错误地将具有 group 的属性报告为已废弃属性 #42071 在 MongoDB 中使用空字符串的 ‘replica-set-name’ 属性将导致 ClusterType=REPLICA_SET #42059 默认 Logback 配置使用过时的 “converterClass” 属性 #42006 📔 文档 关于 spring.jmx.enabled 不适用于第三方库的文件 #42285 更新指向 Log4j2 系统属性(system properties)的链接 #42263 参考指南中的 GraphQL 链接重定向到根目录,而不是特定部分 #42208 参考指南中 “被动接收信息部分(Receive a message reactively section)” 的语法错误 #42200 autotime 启用、percentiles 和 percentiles-historgram 属性被废弃的原因令人困惑。 #42193 在属性文件中用 RFC 9457 取代 RFC 7807 #42190 不支持将配置属性绑定到带有默认值的 Kotlin 值类的文档 #42176 更新文档以反映新的未找到 Handler 的异常行为 #42167 波兰语配置属性参考 #42165 移除指向 “将 Spring Boot JAR 应用转换为 WAR” 的链接,因为该指南已不再可用 #42111 修正 Metric 文档页面上的 StatsD 链接错字 #42109 改进无需构建包的 docker 文档 #42106 改进 “命令行自动补全”中的文档 #42103 测试部分缺少 Kotlin 代码示例 #42094 修复 Colima 的 Docker 配置中的错误命令 #42078 Gradle Plugin AOT 文档中有示例错误 #42046 🔨 依赖升级 升级依赖到 Groovy 4.

使用 OpenFeign 和 CompletableFuture 并行处理多个 HTTP 请求

1、简介 在处理分布式系统时,调用外部服务并保持低延迟是一项至关重要的任务。 本文将带你了解如何使用 OpenFeign 和 CompletableFuture 来并行处理多个 HTTP 请求,处理错误,并设置网络和线程超时。 2、示例项目 为了说明并行请求的用法,我们要实现一个功能,允许客户在网站上购买物品。首先,该服务发出一个请求,根据客户所在国家获取可用的付款方式。其次,它发送一个请求给客户生成有关购买的报告。购买报告不包括有关付款方式的信息。 先添加 spring-cloud-starter-openfeign 依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> 3、创建调用外部依赖的客户端 使用 @FeignClient 注解创建两个指向 localhost:8083 的客户端: @FeignClient(name = "paymentMethodClient", url = "http://localhost:8083") public interface PaymentMethodClient { @RequestMapping(method = RequestMethod.GET, value = "/payment_methods") String getAvailablePaymentMethods(@RequestParam(name = "site_id") String siteId); } 第一个客户端名为 paymentMethodClient。它调用 GET /payment_methods,使用代表客户所在国家/地区的 site_id 请求参数获取可用的付款方式。 第二个客户端如下: @FeignClient(name = "reportClient", url = "http://localhost:8083") public interface ReportClient { @RequestMapping(method = RequestMethod.POST, value = "/reports") void sendReport(@RequestBody String reportRequest); } 我们将其命名为 reportClient,它调用 POST /reports 生成购买报告。