1、概览 Persistence Context(持久化上下文)和 Persistence Unit(持久化单元)是 JPA 中的两个重要概念,用来管理应用中实体的生命周期。
本文将带你了解 JPA 中的 EntityManager(实体管理器) 的作用,以及 Persistence Context 和 Persistence Unit 的重要性和用例。
2、EntityManager 和 EntityManagerFactory 首先来看看 EntityManager 和 EntityManagerFactory 接口,它们在管理持久性(Persistence)、实体和数据库交互方面发挥着重要作用。
2.1、EntityManager EntityManager 是一个与 Persistence Context 交互的接口。它对实体执行 CRUD 操作、跟踪更改并确保在事务提交时与数据库同步。EntityManager 代表一个 Persistence Context,并在事务范围内运行。
2.2、EntityManagerFactory EntityManagerFactory 是一个创建 EntityManager 的接口,有效地发挥着工厂的作用。创建时,EntityManagerFactory 会与特定的 Persistence Unit 关联,从而创建 EntityManager 的实例。
3、PersistenceContext PersistenceContext 是一个短暂的、事务范围的上下文,用于管理实体的生命周期。它代表一组存储在内存中的 “托管实体”,是实体管理器的一级缓存。如果事务开始,就会创建持久化上下文,并最终在事务提交或回滚时关闭或清除。
持久化上下文会自动检测对托管实体所做的更改,并确保所有实体更改与持久化存储(Persistence Storage)同步。
我们可以使用 @PersistenceContext 注解定义持久化上下文(Persistence Context)的类型:
@PersistenceContext private EntityManager entityManager; JPA 中有两种持久化上下文: TRANSACTION 和 EXTENDED。
首先,使用 @Entity 注解创建与 PRODUCT 表相对应的实体:
1、简介 Grafana 实验室受 Prometheus 的启发开发了开源日志聚合系统 Loki。该系统的目的是存储日志数据并编制索引,从而方便高效地查询和分析由不同应用和系统生成的日志。
本文将带你了解如何在 Spring Boot 中使用 Loki 收集和汇总日志,并使用 Grafana 显示日志。
2、运行 Loki 和 Grafana 服务 首先以 Docker 容器的方式启动 Loki 和 Grafana 服务,以便收集和观察日志。
在 docker-compose 文件中定义 Loki 和 Grafana 服务:
version: "3" networks: loki: services: loki: image: grafana/loki:2.9.0 ports: - "3100:3100" command: -config.file=/etc/loki/local-config.yaml networks: - loki grafana: environment: - GF_PATHS_PROVISIONING=/etc/grafana/provisioning - GF_AUTH_ANONYMOUS_ENABLED=true - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin entrypoint: - sh - -euc - | mkdir -p /etc/grafana/provisioning/datasources cat <<EOF > /etc/grafana/provisioning/datasources/ds.
1、概览 API 文档在团队开发中极其重要,特别是在 API 接口及其复杂的情况下,良好的 API 文档不仅能提升开发效率,还能显示产品的质量。如果一家公司的 API 文档写得马马虎虎,那么它的 API 也可能写得马马虎虎。
程序员都讨厌写自己文档和别人不写文档。
本文将带你了解如何使用 Spring REST Docs 自动地生成 API 文档。
2、API 接口 一个简单 API 如下:
@RestController @RequestMapping("/books") public class BookController { private final BookService service; public BookController(BookService service) { this.service = service; } @GetMapping public List<Book> getBooks(@RequestParam(name = "page") Integer page) { return service.getBooks(page); } } 该 API 返回系统中的 Book 数据。不过,由于可用图书数量庞大,不可能一次性返回所有。所以给客户端提供了一个查询参数 page,用于控制数据分页。
而且,需要把该参数设置为必须参数(默认就是必须参数),避免客户端一次性请求过多数据。如果客户端未提交该查询参数,就会收到状态为 400 的错误提示。
3、文档 编写文档的通常方法是 “手写文档”,这意味着开发人员必须把同一件事写两遍。首先写代码,然后再写对应的文档。太麻烦!
文档是一种相当正式的文件,其目标是清晰明了,并不需要太多花里胡哨的东西。因此,我们可以根据代码生成文档,这样就不用重复写同样的东西,而且所有的改动都会反映在文档中。
我们可以通过 Spring REST Docs 来生成 API 文档。不过,它不是从代码中生成文档,因为代码没有提供太多上下文,而是从测试中生成文档。这可以表达相当复杂的案例和示例。另一个好处是,如果测试失败,文档也不会生成。
1、简介 在应用开发中,执行 “更新或插入” 操作(也称为 “upsert”)的需要是很常见的。这个操作涉及将新记录存入数据库表中,如果记录不存在,则插入新记录;如果记录已经存在,则更新现有记录。
本文将带你了解使用 Spring Data JPA 执行 “更新或插入” 操作的不同方法。
2、实体类 定义 CreditCard 实体类用于演示:
@Entity @Table(name="credit_card") public class CreditCard { @Id @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "credit_card_id_seq") @SequenceGenerator(name = "credit_card_id_seq", sequenceName = "credit_card_id_seq", allocationSize = 1) private Long id; private String cardNumber; private String expiryDate; private Long customerId; // Get / Set 方法省略 } 3、实现 本文介绍三种不同的方法来实现 “更新或插入”。
3.1、使用 Repository 方法 使用从 CrudRepository 接口继承的 save(entity) 方法在 Repository 中编写一个带事务的 default 方法。
1、简介 缓存是一种有效的策略,当执行结果在一段已知时间内没有变化时,可以避免重复执行逻辑,从而提高性能。
Spring Boot 提供了 @Cacheable 注解,可以在方法上定义该注解,它就会缓存方法的结果。在某些情况下,例如在测试环境中进行测试时,我们可能需要禁用缓存来观察某些修改后的行为。
本文将带你了解如何配置 Spring Boot 中的缓存,以及如何在需要时禁用缓存。
2、缓存配置 设置一个简单的用例,通过 ISBN(国际标准书号)查询图书评论,并在某个逻辑中使用 @Cacheable 对该方法返回的结果进行缓存。
实体类 BookReview 如下,它包含 bookRating、isbn 等信息:
@Entity @Table(name="BOOK_REVIEWS") public class BookReview { @Id @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "book_reviews_reviews_id_seq") @SequenceGenerator(name = "book_reviews_reviews_id_seq", sequenceName = "book_reviews_reviews_id_seq", allocationSize = 1) private Long reviewsId; private String userId; private String isbn; private String bookRating; // Get / Set 方法省略 } 在 BookRepository 中添加一个简单的 findByIsbn() 方法,用于按 isbn 查询书评:
public interface BookRepository extends JpaRepository<BookReview, Long> { List<BookReview> findByIsbn(String isbn); } BookReviewsLogic 类包含一个在 BookRepository 中调用 findByIsbn() 的方法。我们添加了 @Cacheable 注解,将指定 isbn 的结果缓存在 book_reviews 缓存中:
1、概览 当 PostgreSQL 服务器无法接受客户端应用的连接请求时,就会抛出 PostgreSQL PSQLException:FATAL: sorry, too many clients already 这个异常。
本文将带你了解如何解决以及防止这个异常。
2、理解问题 DB 服务器启动时的连接数有限。有时,连接会用完。因此,数据库服务器无法提供新的连接。这时,它就会抛出异常:FATAL: sorry, too many clients already。
首先,来了解一下这个问题是如何、何时以及为何出现的。假设有四个 Client 应用连接到 PostgreSQL 数据库:
大多数情况下,应用会在启动时创建数据库连接池。假设数据库管理员为 PostgreSQL 数据库服务器配置了最多 90 个连接。需要注意的是,数据库会保留一些连接供内部使用。实际可供客户端使用的连接数甚至更少。运维为每个客户端应用配置的连接池大小为 30。
现在,假设运维从 Client-1 开始依次启动 Client 应用。当 Client-4 试图启动时,由于 Client-1、Client-2 和 Client-3 已经创建并阻塞了 90 个连接。因此,当 Client-4 向数据库服务器请求出创建 30 个连接时,服务器拒绝了请求,并显示错误 “FATAL: sorry, too many clients already”。
当开发人员尝试使用 psql、psgAdmin、DBeaver 等数据库管理工具连接 PostgreSQL 服务器时,也会出现该错误。因为这些工具也会尝试获取与数据库的连接,如果连接不足,它们也可能遇到同样的错误。
3、排除故障 首先,通过在 PostgreSQL 数据库中运行查询来确定最大连接数:
show max_connections 默认情况下,该值为 100,可以通过修改数据库配置文件 postgresql.conf 中的 max_connections 属性来 设置 它:
Spring Security 是一个功能强大且可高度定制的安全框架,它提供了一套完整的解决方案,用于保护基于 Spring 的应用。在 Spring Security 中,路径匹配是权限控制的核心部分,它决定了哪些请求可以访问特定的资源。本文将带你详细了解 Spring Security 中的路径匹配策略,并提供相应的代码示例。
在旧版的 Spring Security 中,路径匹配方法有很多,但是新版 Spring Security 对这些方法进行了统一的封装,都是调用 requestMatchers 方法进行处理:
public C requestMatchers(RequestMatcher... requestMatchers) { Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest"); return chainRequestMatchers(Arrays.asList(requestMatchers)); } requestMatchers 方法接收一个 RequestMatcher 类型的参数,RequestMatcher 是一个接口,这个接口是一个用来确定 HTTP 请求是否与给定的模式匹配的工具。这个接口提供了一种灵活的方式来定义请求的匹配规则,从而可以对不同的请求执行不同的安全策略。
所以在新版 Spring Security 中,不同的路径匹配分方案实际上就是不同的 RequestMatcher 的实现类。
1. AntPathRequestMatcher AntPathRequestMatcher 是 Spring 中最常用的请求匹配器之一,它使用 Ant 风格的路径模式来匹配请求的 URI。
1.1 什么是 Ant 风格的路径模式 Ant 风格的路径模式(Ant Path Matching)是一种用于资源定位的模式匹配规则,它源自 Apache Ant 这个 Java 构建工具。在 Ant 中,这种模式被用来指定文件系统中的文件和目录。由于其简单性和灵活性,Ant 风格的路径模式也被其他许多框架和应用程序所采用,包括 Spring Security。
1、概览 Protocol Buffer (Protobuf) 是一种用于序列化结构化数据的二进制格式。它是由 Google 开发的,并且被广泛应用于跨平台和跨语言的数据通信。Protocol Buffer 使用简洁、高效的编码方案,可以将结构化数据定义为消息类型,并生成针对不同编程语言的数据访问代码。这使得在不同的系统之间传输和解析数据变得更加简单和高效。Protocol Buffer 具有广泛的支持,包括 Java、C++、Python、Golang 等编程语言。
Protobuf Timestamp 类型代表一个时间点,与任何特定时区无关。本文将带你了解如何把 Protobuf Timestamp 实例转换为 Java 的本地时间类型,如 LocalDate。
2、Maven 依赖 在 pom.xml 中添加 protobuf-java 依赖:
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>4.26.1</version> </dependency> 该依赖提供了 Timestamp 和其他与 Protobuf 相关的类。
3、Timestamp 类 Protobuf Timestamp 类表示自 Unix 纪元以来的时间点。与时区或本地日历没有关系。
它表示的是某个时间点的秒数和纳秒数。下面是使用 Java Instant 对象计算当前时间戳的示例:
Instant currentTimestamp = Instant.now(); Timestamp timestamp = Timestamp.newBuilder() .setSeconds(currentTimestamp.getEpochSecond()) .setNanos(currentTimestamp.getNano()) .build(); 如上,通过 Instant 对象计算时间戳。首先,创建一个 Instant 对象,表示给定点的日期和时间。然后,提取秒和纳秒,并将它们传递给 Timestamp 实例。
4、把 Timestamp 实例转换为 LocalDate 在将 Timestamp 转换为 LocalDate 时,必须考虑时区及其与 UTC 的相关偏移,以准确表示本地日期。要将 Timestamp 转换为 LocalDate,首先要创建一个具有特定秒和纳秒的 Timestamp 实例:
1、概览 Spring Data MongoDB 的 MongoRepository 接口提供了一种简单的方式与 MongoDB Collection 进行交互。
本文将带你了解如何在 MongoRepository 中使用 limit 和 skip。
2、初始设置 首先,创建一个名为 StudentRepository 的 Repository,用于存储 Student 信息:
public interface StudentRepository extends MongoRepository<Student, String> {} 然后,向该 Repository 添加一些 Student 示例数据:
@Before public void setUp() { Student student1 = new Student("A", "Abraham", 15L); Student student2 = new Student("B", "Usman", 30L); Student student3 = new Student("C", "David", 20L); Student student4 = new Student("D", "Tina", 45L); Student student5 = new Student("E", "Maria", 33L); studentList = Arrays.
1、概览 日志记录是任何软件应用的重要组件,用于监控、调试和维护系统的健康状况。在 Spring Boot 生态系统中,Logback 作为默认的日志记录框架,提供了灵活和强大的功能。虽然 Spring Boot 简化了应用的许多方面,但有时仍然需要通过 logback.xml 配置文件来配置 Logback 以满足特定要求。
本文将会带你了解如何在 Java、Spring Boot 应用中指定 logback.xml 配置文件的位置。
2、logback.xml logback.xml 文件是 Logback 的配置文件,用于定义日志记录规则、appender 和日志格式(log format)。
默认情况下,Logback 会在 classpath 根目录中搜索该文件。这意味着将 logback.xml 文件放在 Spring Boot 项目的 src/main/resources 目录中就足够了,因为 Logback 会在运行时自动检测到它。不过,在某些情况下,自定义其位置也是必要的。
3、指定 logback.xml 位置 3.1、使用 System Properties 如果 logback.xml 配置文件不在打包后的 Jar 中,可以使用 System Properties 指定其位置。例如,在运行 Spring Boot 应用时,可以使用 JVM 参数:
java -Dlogback.configurationFile=/path/to/logback.xml -jar application.jar 命令 -Dlogback.configurationFile=/path/to/logback.xml 将系统属性 logback.configurationFile 设置为指定路径,指定 Logback 使用提供的配置文件。
3.2、编程式配置 logback.