十七:Spring Boot 依赖(2)-- spring-boot-starter-data-jpa 依赖详解

目录

1. 理解 JPA(Java Persistence API)

1.1 什么是 JPA?

1.2 JPA 与 Hibernate 的关系

1.3 JPA 的基本注解:@Entity, @Table, @Id, @GeneratedValue

1.4 JPA 与数据库表的映射

2. Spring Data JPA 概述

2.1 什么是 Spring Data JPA?

2.2 spring-boot-starter-data-jpa 的作用

2.3 配置 spring-boot-starter-data-jpa 依赖

3. Spring Boot 和 JPA 整合案例

3.1 创建一个基本的 CRUD Web 应用

3.2 Spring Boot 集成 JPA 的实践

3.2.1 引入基本的 Spring Data JPA 依赖

3.2.2 引入数据库连接池(默认使用 HikariCP)推荐默认的就行

使用 DBCP2 连接池

使用 C3P0 连接池

3.2.3 数据库驱动

3.2.4 配置 application.properties 或 application.yml

4. 实体类与数据库表映射

4.1 数据库建表语句

4.2 创建一个 JPA 实体类

4.2 使用 JPA 的基本类型映射(如:@Column, @OneToMany, @ManyToOne 等)

JPA 提供了许多注解来描述实体类与数据库表之间的关系,包括对列、主键、关系的映射。

4.2.1 @Column

4.2.2 @ManyToOne 和 @OneToMany

4.2.3 @OneToOne

4.2.4 @ManyToMany

5. Spring Data JPA Repository

5.1 JpaRepository 和 CrudRepository 接口

5.1.1 ​​​​​​​CrudRepository 接口

5.1.2 JpaRepository 接口(推荐,实现的多)

5.2 创建 Repository 接口

5.3 常用的 CRUD 操作(保存、查询、删除、更新)

5.4 自定义查询方法(如:通过方法名自动生成查询)

5.5 使用 @Query 注解编写自定义 SQL 查询

5.5.1 使用 JPQL(推荐方式)

5.5.2 使用原生 SQL

5.5.3 使用 @Modifying 和 @Transactional 进行更新/删除操作

6. JPA 查询功能

6.1 JPQL查询

6.2 Criteria API(动态查询)

6.3 使用 Spring Data JPA 提供的分页与排序功能

6.3.1 分页

6.3.2 排序​​​​​​​​​​​​​​​​​​​​​

7. 事务管理

7.1 什么是事务?

7.2 Spring 的事务管理基础

7.3 使用 @Transactional 注解

7.4 事务的传播行为和隔离级别

7.5 事务回滚机制

8. 配置与优化

8.1 配置数据源(DataSource)

8.2 使用 application.properties 配置数据库连接池

8.3 配置 JPA 的 Hibernate 属性(如:DDL 自动生成策略、SQL 日志输出等)

8.3.1 ​​​​​​​​​​​​​​配置 Hibernate 的 DDL 自动生成策略

8.3.2 配置 Hibernate 的 SQL 日志输出


  • 1. 理解 JPA(Java Persistence API)

    • 1.1 什么是 JPA?

      • JPA(Java Persistence API)是 Java 平台的一部分,专门用于简化 Java 应用程序与关系型数据库之间的交互。它定义了一种标准的方式来映射 Java 对象到数据库表,同时提供了操作数据库(增、删、改、查)的接口,支持对象关系映射(ORM)。JPA 作为一种规范,定义了如何在 Java 应用程序中实现持久化,但并没有提供具体的实现。

        JPA 的实现可以有多个,其中最常见的实现是 Hibernate,但也有其他实现,如 EclipseLink、OpenJPA 等。

    • 1.2 JPA 与 Hibernate 的关系

      • Hibernate 是一个非常流行的 JPA 实现。它是一个开源的 ORM 框架,遵循了 JPA 的规范,并提供了一些额外的功能,比如自动生成 SQL、缓存机制等。简单来说,Hibernate 实现了 JPA 规范,它可以作为 JPA 的一个持久化提供者。

      • JPA 是一个规范,它规定了 Java 对象和关系型数据库之间的映射规则以及操作数据库的 API。

      • Hibernate 是一个实现,它提供了具体的代码来执行 JPA 规范中定义的操作。

      • 例如,你可以使用 Hibernate 来实现 JPA 标准的接口,或者直接使用 Hibernate 提供的扩展功能。JPA 的目标是解耦持久化层,使得应用程序不依赖于某一个具体的实现,而是遵循 JPA 规范,便于切换实现。

    • 1.3 JPA 的基本注解:@Entity, @Table, @Id, @GeneratedValue

      • 在 JPA 中,注解是实现对象关系映射的关键。常见的注解包括:

      • @Entity:标识一个类是一个实体类,表示该类的实例将会与数据库中的一条记录映射。每个 @Entity 注解的类对应数据库中的一张表。

        • @Entity
          public class User {// 类体
          }
          
      • @Table:指定数据库表的名称。如果不使用该注解,默认情况下,实体类的名字将会被用作表名。通过 @Table 可以自定义表名以及其他表级别的配置(如 schema、catalog 等)。

        • @Entity
          @Table(name = "users")
          public class User {// 类体
          }
          
      • @Id:指定实体类的主键字段。每个实体类必须至少有一个主键字段,JPA 使用该字段来唯一标识实体类的对象。

        • @Entity
          public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;// 其他字段
          }
          
      • @GeneratedValue:指定主键的生成策略。通常与 @Id 一起使用,表示主键的值如何自动生成。可以选择不同的生成策略,如 AUTOIDENTITYSEQUENCE 等。

        • GenerationType.AUTO:JPA 容器根据数据库的不同选择合适的生成策略。
        • GenerationType.IDENTITY:通过数据库的自增列生成主键值。
        • GenerationType.SEQUENCE:使用数据库序列生成主键值(通常用于数据库支持序列的情况)。
        • GenerationType.TABLE:使用一个特殊的数据库表来生成主键(这种方式比较少见)。
        • @Entity
          public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;// 其他字段
          }
          
    • 1.4 JPA 与数据库表的映射

      • JPA 将 Java 对象(类)和数据库表之间进行映射,这种映射关系主要由注解和配置来定义。JPA 实现了对象关系映射(ORM),它能够将数据库中的记录转换为 Java 对象,并允许开发人员通过操作对象来间接操作数据库。

      • 常见的映射关系如下:

        • 一对一关系(@OneToOne):一个实体对应另一个实体的一个实例。

        • 一对多关系(@OneToMany):一个实体对应多个实体。

        • 多对一关系(@ManyToOne):多个实体对应一个实体。

        • 多对多关系(@ManyToMany):多个实体对应多个实体。

      • 举个例子,假设我们有一个 User 实体类和一个 Address 实体类,一个用户可能有多个地址(多对一关系),那么我们可以使用 @OneToMany@ManyToOne 来进行映射:

      • @Entity
        public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@OneToMany(mappedBy = "user")private List<Address> addresses;// 其他字段和方法
        }@Entity
        public class Address {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@ManyToOne@JoinColumn(name = "user_id")private User user;}
        
  • 2. Spring Data JPA 概述

    • 2.1 什么是 Spring Data JPA?

      • Spring Data JPA 是 Spring Data 项目的一个子项目,它简化了基于 JPA(Java Persistence API)进行数据库操作的开发。Spring Data JPA 基于 JPA 规范,结合 Spring 的优势,提供了对 JPA 持久化技术的简化支持,特别是在 Spring Boot 应用中使用时,极大地减少了样板代码(boilerplate code)。

        Spring Data JPA 通过提供一个简单的接口 JpaRepository 和一些其他的 CRUD 接口,使开发者可以轻松实现对数据库的基本操作,如增、删、改、查等,而无需编写实现代码。它通过动态代理技术,自动生成实现类,简化了开发过程。

        核心特性

        • 简化 CRUD 操作:无需编写实现代码,直接通过继承接口来使用常见的数据库操作。

        • 基于 JPA:继承了 JPA 的标准特性,如实体类映射、查询方法等。

        • 查询方法自动生成:Spring Data JPA 根据方法名自动生成 SQL 查询,无需手写 SQL。

        • 分页和排序支持:内置分页、排序功能,支持复杂的查询。

    • 2.2 spring-boot-starter-data-jpa 的作用

      • spring-boot-starter-data-jpa 是 Spring Boot 提供的一个启动器(starter),用于集成和配置 Spring Data JPA。在应用中引入该依赖后,Spring Boot 会自动配置与 JPA 相关的 Bean,简化了 JPA 的配置和初始化工作。

      • 作用

        • 自动配置数据源(DataSource)、JPA 相关的配置(如 EntityManagerFactory)、事务管理器(PlatformTransactionManager)等。

        • 集成常见的 JPA 实现(如 Hibernate),并提供简单的配置方式。

        • 支持自动创建数据库表和执行初始化 SQL(根据 spring.jpa.hibernate.ddl-auto 配置项)。

        • 提供分页、排序等功能,结合 Spring Data JPA 的接口,可以非常方便地执行复杂查询。

      • 自动配置

        • 配置数据库连接、实体类管理、事务管理等。

        • 使用 JpaRepository 等接口简化持久化操作。

    • 2.3 配置 spring-boot-starter-data-jpa 依赖

      • 要在 Spring Boot 项目中使用 Spring Data JPA,首先需要在项目的 pom.xml 文件中添加 spring-boot-starter-data-jpa 依赖。这个依赖会自动引入 Spring Data JPA 和 Hibernate 等相关库。
      • pom.xml 中添加 spring-boot-starter-data-jpa 依赖。
        •     <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>
  • 3. Spring Boot 和 JPA 整合案例

    • 3.1 创建一个基本的 CRUD Web 应用

    • 3.2 Spring Boot 集成 JPA 的实践

      • 3.2.1 引入基本的 Spring Data JPA 依赖

        • <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
          </dependency>
      • 3.2.2 引入数据库连接池(默认使用 HikariCP)推荐默认的就行

        • Spring Boot 默认使用 HikariCP 作为连接池,它不需要额外的依赖。如果你使用的是 HikariCP,你不需要手动添加依赖,因为它已经包含在 Spring Boot 的默认配置中。

        • 如果你需要使用其他连接池(例如 DBCP2 或 C3P0),可以选择手动添加相应的依赖:

          • 使用 DBCP2 连接池
            • <dependency><groupId>org.apache.commons</groupId><artifactId>commons-dbcp2</artifactId>
              </dependency>
              
          • 使用 C3P0 连接池
            • <dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId>
              </dependency>
              
      • 3.2.3 数据库驱动

        • 根据你使用的数据库,你需要添加相应的数据库驱动。例如,假设你使用 MySQL,你需要添加 MySQL 驱动:
        • <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
          </dependency>
          
      • 3.2.4 配置 application.propertiesapplication.yml

        • application.properties
          • # 数据库配置
            spring.datasource.url=jdbc:mysql://localhost:3306/lirui?useSSL=false&serverTimezone=UTC
            spring.datasource.username=root
            spring.datasource.password=root
            spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# 使用HikariCP作为连接池(Spring Boot默认使用HikariCP)
            spring.datasource.hikari.maximum-pool-size=10
            spring.datasource.hikari.minimum-idle=5# JPA配置
            spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
            spring.jpa.hibernate.ddl-auto=update
            spring.jpa.show-sql=true
            spring.jpa.properties.hibernate.format_sql=true
            
        • application.yml
          • spring:datasource:url: jdbc:mysql://localhost:3306/lirui?useSSL=false&serverTimezone=UTCusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driverjpa:hibernate:ddl-auto: updateshow-sql: truedatabase-platform: org.hibernate.dialect.MySQL5Dialecthikari:maximum-pool-size: 10minimum-idle: 5
            
  • 4. 实体类与数据库表映射

    • 4.1 数据库建表语句

      • CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) NOT NULL,`email` varchar(255) NOT NULL,PRIMARY KEY (`id`)
        ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
    • 4.2 创建一个 JPA 实体类

      • package com.lirui.springbootmoduledemo.dao;import javax.persistence.*;@Entity  // 标识该类为一个 JPA 实体类
        @Table(name = "users")  // 映射到数据库中的 users 表
        public class User {@Id  // 主键标识@GeneratedValue(strategy = GenerationType.IDENTITY)  // 自增主键@Column(name = "id")  // 映射到数据库中的 id 列private Integer id;@Column(name = "name", nullable = false, length = 255)  // 映射到 name 列private String name;@Column(name = "email", nullable = false, length = 255)  // 映射到 email 列private String email;// Getter 和 Setter 方法public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", email='" + email + '\'' +'}';}
        }
      • @Entity:声明 User 类是一个 JPA 实体类,Spring Data JPA 会根据该类生成对应的数据库表操作。

      • @Table(name = "users"):指定实体类对应的数据库表名为 users。如果类名与表名相同,可以省略这个注解。

      • @Id:标识该字段是实体的主键(id 字段)。

      • @GeneratedValue(strategy = GenerationType.IDENTITY):指定主键的生成策略为 IDENTITY,表示使用数据库的自增机制。适用于 MySQL 等数据库。

      • @Column(name = "column_name"):映射实体类字段到数据库表中的列(如 nameemail)。使用 nullable = false 来指定列不允许为 NULL,并且可以设置列的最大长度(如 length = 255)。

      • Integer 类型的 id 字段:我们将 id 定义为 Integer 类型,这样它可以自动与数据库中的 int 类型映射。如果你更倾向于使用 Long 类型,也可以使用 Long 类型。

    • 4.2 使用 JPA 的基本类型映射(如:@Column, @OneToMany, @ManyToOne 等)

      • JPA 提供了许多注解来描述实体类与数据库表之间的关系,包括对列、主键、关系的映射。

      • 4.2.1 @Column

        • 映射实体类属性到数据库表的列。
        • 可设置属性(如:nullablelengthuniquecolumnDefinition 等)。
          • nullable

            • 定义列是否允许 NULL 值。

            • 默认值true(表示列允许为 NULL)。

            • 使用场景:如果我们希望某个字段在数据库中不能为空,可以将 nullable 设置为 false,表示该列必须有值。

          • length

            • 定义字符串类型的列(如 String)的最大长度。

            • 使用场景:主要用于设置数据库中 VARCHAR 类型的字段的最大长度。如果没有显式设置,默认长度为 255。

            • 适用类型StringcharCharacter 类型。

          • unique

            • 功能:指定列是否应该是唯一的。

            • 默认值false(表示列不要求唯一)。

            • 使用场景:如果我们希望某个字段的值在数据库中是唯一的,可以设置 unique = true,表示该列的值在数据库表中必须是唯一的。

          • columnDefinition

            • 功能:指定列的具体定义,包括数据类型、默认值、约束等。

            • 使用场景:当我们需要对列进行更精细的控制,例如设置数据库列的数据类型、默认值、约束条件等时,可以使用 columnDefinition。它允许你直接写 SQL 语句来控制列的定义。

            • @Column(columnDefinition = "VARCHAR(100) NOT NULL DEFAULT 'Unknown'")  
              private String username;
              
          • name

            • 定义数据库中列的名称。如果不设置,默认使用字段名。

          • insertable

            • 指定是否允许在插入时写入该列。默认值是 true

          • updatable

            • 指定是否允许更新该列。默认值是 true

          • precisionscale

            • 主要用于 BigDecimal 类型,用于定义列的精度和小数位数。

      • 4.2.2 @ManyToOne@OneToMany

        • ​​​​​@ManyToOne:表示多对一的关系。例如,一个用户有多个订单,但每个订单只能属于一个用户。

        • @OneToMany:表示一对多的关系。例如,一个用户可以有多个订单。

        • import javax.persistence.Entity;
          import javax.persistence.Id;
          import javax.persistence.OneToMany;
          import java.util.List;@Entity
          @Table(name = "user")
          public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;@OneToMany(mappedBy = "user")  // 通过 user 字段映射到 Orderprivate List<Order> orders;  // 一对多关系// Getter 和 Setter
          }
          
          import javax.persistence.Entity;
          import javax.persistence.Id;
          import javax.persistence.ManyToOne;@Entity
          @Table(name = "order")
          public class Order {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String productName;@ManyToOne  // 多对一关系@JoinColumn(name = "user_id")  // 映射外键private User user;  // 每个订单对应一个用户// Getter 和 Setter
          }
          
      • 4.2.3 @OneToOne

        • ​​​​​​​​​​​​​​如果实体之间存在一对一关系,可以使用 @OneToOne 注解。

          @Entity
          public class Profile {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String bio;@OneToOne@JoinColumn(name = "user_id")  // 外键字段private User user;  // 一对一关系// Getter 和 Setter
          }
          
      • 4.2.4 @ManyToMany

        • 如果两个实体之间存在多对多的关系,可以使用 @ManyToMany 注解。

          @Entity
          public class Course {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@ManyToMany@JoinTable(name = "course_student", joinColumns = @JoinColumn(name = "course_id"), inverseJoinColumns = @JoinColumn(name = "student_id"))private List<Student> students;// Getter 和 Setter
          }
          

  • 5. Spring Data JPA Repository

    • 5.1 JpaRepositoryCrudRepository 接口

      • 5.1.1 ​​​​​​​CrudRepository 接口

        • ​​​​​​​CrudRepository 是 Spring Data JPA 提供的基本接口之一,它提供了最基本的 CRUD 操作方法。它是所有 JPA Repository 接口的基础。

        • 常用的方法:

          • save(S entity):保存实体。

          • findById(ID id):根据主键查找实体。

          • findAll():查找所有实体。

          • deleteById(ID id):根据 ID 删除实体。

      • 5.1.2 JpaRepository 接口(推荐,实现的多)

        • ​​​​​​​​​​​​​​JpaRepository 扩展了 PagingAndSortingRepositoryCrudRepository,因此它不仅提供了 CRUD 功能,还支持分页和排序功能。

        • 常用的方法:

          • findAll(Pageable pageable):分页查询。

          • findAll(Sort sort):排序查询。

          • flush():刷新持久化上下文。

          • saveAndFlush(S entity):保存并立即刷新实体。

    • 5.2 创建 Repository 接口

      • ​​​​​​​​​​​​​​Spring Data JPA 中,我们只需要定义一个接口并继承 JpaRepositoryCrudRepository,Spring 会自动实现所有方法。

      • @Repository  // 标记为一个 Spring 的 Repository
        public interface UserRepository extends JpaRepository<User, Integer> {// 可以在这里定义查询方法,例如:// List<User> findByName(String name);
        }
    • 5.3 常用的 CRUD 操作(保存、查询、删除、更新)

      • ​​​​​​​
        @Service  // 标注为 Spring 管理的 Service 类
        public class UserService {@Autowiredprivate UserRepository userRepository;  // 注入 UserRepository// 保存用户public User saveUser(User user) {return userRepository.save(user);  // 调用 UserRepository 的 save 方法}// 获取所有用户public List<User> getAllUsers() {return userRepository.findAll();  // 获取所有用户}// 根据 ID 查找用户public Optional<User> getUserById(Integer id) {return userRepository.findById(id);  // 根据 ID 查找用户}// 删除用户public void deleteUser(Integer id) {userRepository.deleteById(id);  // 删除用户}
        }

    • 5.4 自定义查询方法(如:通过方法名自动生成查询)

      • ​​​​​​​Spring Data JPA 支持通过方法名自动生成查询。只需要按照一定的规则命名方法,Spring Data JPA 就能自动实现查询。

      • 常见的查询方法命名规则:
        • 根据属性查找findBy<属性名>
          例如:findByName(String name),表示根据 name 属性查找。

        • 根据多个属性查找findBy<属性1>And<属性2>
          例如:findByNameAndEmail(String name, String email),表示根据 nameemail 属性查找。

        • 根据属性模糊查找findBy<属性名>Like
          例如:findByNameLike(String name),表示根据 name 属性模糊查找。

      • @Repository  // 标记为一个 Spring 的 Repository
        public interface UserRepository extends JpaRepository<User, Integer> {// 可以在这里定义查询方法,例如:List<User> findByName(String name);  // 根据名字查询用户List<User> findByEmail(String email);  // 根据 email 查询用户List<User> findByNameAndEmail(String name, String email);  // 根据名字和 email 查询用户List<User> findByNameLike(String name);  // 根据名字模糊查询用户
        }
    • 5.5 使用 @Query 注解编写自定义 SQL 查询

      • ​​​​​​​如果方法名不能满足需求,或者你需要更复杂的查询,可以使用 @Query 注解来编写自定义的 JPQL或者原生 SQL 查询。

      • 5.5.1 使用 JPQL(推荐方式)

        JPQL 是针对实体对象的查询语言,而不是针对数据库表的 SQL 语言。你可以使用 @Query 注解来编写 JPQL 查询。

        • package com.lirui.springbootmoduledemo.repository;import com.lirui.springbootmoduledemo.dao.User;
          import org.springframework.data.jpa.repository.JpaRepository;
          import org.springframework.data.jpa.repository.Query;
          import org.springframework.stereotype.Repository;import java.util.List;@Repository  // 标记为一个 Spring 的 Repository
          public interface UserRepository extends JpaRepository<User, Integer> {// 可以在这里定义查询方法,例如:@Query("SELECT u FROM User u WHERE u.name = ?1")  // JPQL 查询List<User> findByName(String name);  // 根据名字查询用户List<User> findByEmail(String email);  // 根据 email 查询用户List<User> findByNameAndEmail(String name, String email);  // 根据名字和 email 查询用户List<User> findByNameLike(String name);  // 根据名字模糊查询用户
          }
      • 5.5.2 使用原生 SQL

        如果你需要直接使用原生 SQL 查询,可以通过 nativeQuery = true 来指定。

        •     @Query(value = "SELECT * FROM users WHERE email LIKE %?1%", nativeQuery = true)  // 原生 SQL 使用 LIKE 查询List<User> findByEmail(String email);  // 根据 email 查询用户
      • 5.5.3 使用 @Modifying@Transactional 进行更新/删除操作

        • 如果你需要执行更新或删除操作,必须使用 @Modifying 注解,并且方法应该是事务性的。

        • package com.lirui.springbootmoduledemo.repository;import com.lirui.springbootmoduledemo.dao.User;
          import org.springframework.data.jpa.repository.JpaRepository;
          import org.springframework.data.jpa.repository.Modifying;
          import org.springframework.data.jpa.repository.Query;
          import org.springframework.stereotype.Repository;import javax.transaction.Transactional;
          import java.util.List;@Repository  // 标记为一个 Spring 的 Repository
          public interface UserRepository extends JpaRepository<User, Integer> {// 可以在这里定义查询方法,例如:@Query("SELECT u FROM User u WHERE u.name = ?1")  // JPQL 查询List<User> findByName(String name);  // 根据名字查询用户@Query(value = "SELECT * FROM users WHERE email LIKE %?1%", nativeQuery = true)  // 原生 SQL 使用 LIKE 查询List<User> findByEmail(String email);  // 根据 email 查询用户List<User> findByNameAndEmail(String name, String email);  // 根据名字和 email 查询用户List<User> findByNameLike(String name);  // 根据名字模糊查询用户@Modifying  // 标注为修改操作@Transactional  // 事务支持@Query("UPDATE User u SET u.name = ?1 WHERE u.id = ?2")int updateUserNameById(String name, Integer id);@Modifying@Transactional@Query("DELETE FROM User u WHERE u.id = ?1")void deleteUserById(Integer id);
          }
  • 6. JPA 查询功能

    • 6.1 JPQL查询

      • ​​​​​​​同上
    • 6.2 Criteria API(动态查询)

      • ​​​​​​​Criteria API 是 JPA 提供的一个用于构建动态查询的 API,它允许我们通过编程方式构造查询,适用于那些查询条件动态变化的情况。使用 Criteria API,可以避免拼接字符串,避免 SQL 注入风险。

      • Criteria API 的常用组件:

        • CriteriaBuilder:用于创建查询的各种条件和表达式。

        • CriteriaQuery:表示查询的具体内容。

        • Root:表示查询的根对象,通常是实体类。

        • Predicate:表示查询条件。

      • package com.lirui.springbootmoduledemo.service;import com.lirui.springbootmoduledemo.dao.User;
        import com.lirui.springbootmoduledemo.repository.UserRepository;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.stereotype.Service;import javax.persistence.EntityManager;
        import javax.persistence.criteria.CriteriaBuilder;
        import javax.persistence.criteria.CriteriaQuery;
        import javax.persistence.criteria.Predicate;
        import javax.persistence.criteria.Root;
        import java.util.List;
        import java.util.Optional;@Service  // 标注为 Spring 管理的 Service 类
        public class UserService {@Autowiredprivate UserRepository userRepository;  // 注入 UserRepository@Autowiredprivate EntityManager entityManager;public List<User> findUsersByCriteria(String name, String email) {CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);Root<User> userRoot = criteriaQuery.from(User.class);  // 设置查询根对象// 构建查询条件Predicate predicate = criteriaBuilder.conjunction();  // 创建一个“与”的条件if (name != null) {predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(userRoot.get("name"), name));  // 添加 name 的条件}if (email != null) {predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(userRoot.get("email"), email));  // 添加 email 的条件}criteriaQuery.where(predicate);  // 设置查询条件return entityManager.createQuery(criteriaQuery).getResultList();  // 执行查询}// 保存用户public User saveUser(User user) {return userRepository.save(user);  // 调用 UserRepository 的 save 方法}// 获取所有用户public List<User> getAllUsers() {return userRepository.findAll();  // 获取所有用户}// 根据 ID 查找用户public Optional<User> getUserById(Integer id) {return userRepository.findById(id);  // 根据 ID 查找用户}// 删除用户public void deleteUser(Integer id) {userRepository.deleteById(id);  // 删除用户}
        }

    • 6.3 使用 Spring Data JPA 提供的分页与排序功能

      • 6.3.1 分页

        • ​​​​​​​Spring Data JPA 为我们提供了 Pageable 接口,用来表示分页请求。Pageable 可以指定页码(page)和每页大小(size)。
        •     @Query("SELECT u FROM User u WHERE u.name = ?1")  // JPQL 查询List<User> findByName(String name, Pageable pageable);  // 根据名字查询用户
              public User findByName(User user) {Pageable pageable = PageRequest.of(0, 10);  // 创建 Pageable 实例List<User> byName = userRepository.findByName(user.getName(), pageable);return byName.get(0);  // 调用 UserRepository 的 save 方法}
      • 6.3.2 排序​​​​​​​​​​​​​​​​​​​​​

        • ​​​​​​​用法一样
        •     @Query("SELECT u FROM User u WHERE u.name = ?1")  // JPQL 查询List<User> findByName(String name, Pageable pageable, Sort sort);  // 根据名字查询用户
          
              public User findByName(User user) {Pageable pageable = PageRequest.of(0, 10);  // 创建 Pageable 实例Sort sort = Sort.by(Sort.Order.asc("name"));  // 根据 name 字段升序排序List<User> byName = userRepository.findByName(user.getName(), pageable,sort);return byName.get(0);  // 调用 UserRepository 的 save 方法}
          
  • 7. 事务管理

    • 7.1 什么是事务?

      • ​​​​​​​​​​​​​​事务(Transaction) 是一组操作的集合,这些操作要么全部执行成功,要么在出现问题时全部回滚。事务是数据库管理系统(DBMS)中用于确保数据一致性、完整性、可靠性的一个关键概念。
      • 事务的 ACID 特性

        • 原子性(Atomicity):事务中的操作要么全部成功,要么全部失败,不会出现部分成功的情况。
        • 一致性(Consistency):事务执行前后,数据库的状态必须是合法的。
        • 隔离性(Isolation):一个事务的执行不应该受到其他事务的干扰,事务的执行结果对其他事务是隔离的。
        • 持久性(Durability):一旦事务提交,操作的结果会永久保存到数据库中,即使系统崩溃也不会丢失。
    • 7.2 Spring 的事务管理基础

      • ​​​​​​​Spring 提供了两种主要的事务管理方式:

      • 声明式事务管理:通过 @Transactional 注解或 AOP 配置来管理事务。

      • 编程式事务管理:通过编程方式(即通过 TransactionTemplatePlatformTransactionManager)显式控制事务的开始、提交和回滚。

      • 声明式事务管理是 Spring 推荐的事务管理方式,通常使用 @Transactional 注解。

    • 7.3 使用 @Transactional 注解

      • ​​​​​​​​​​​​​​Spring 的 @Transactional 注解可以用来声明式地管理事务。通过将其应用于方法或类上,Spring 会自动在方法执行时开启事务,方法执行结束时提交事务,若方法抛出异常则回滚事务。

        基本使用

        • 应用于类:应用于类级别时,类中的所有方法都会被事务管理。

        • 应用于方法:应用于方法时,只有该方法会被事务管理。

      • @Transactional 常用属性:

        • propagation:定义事务的传播行为(如如何处理事务的嵌套)。

        • isolation:定义事务的隔离级别(如多个事务之间如何隔离)。

        • rollbackFor:指定哪些异常会导致事务回滚。

        • noRollbackFor:指定哪些异常不会导致事务回滚。

        • timeout:指定事务的超时时间(单位:秒)。

        • readOnly:设置事务是否为只读事务,优化数据库性能(对于只读取数据的操作)。

        • value:指定事务管理器的名字,默认情况下 Spring 会使用默认的事务管理器。

    • 7.4 事务的传播行为和隔离级别

      • ​​​​​​​​​​​​​​事务传播行为(Propagation)

        • 事务传播行为定义了一个事务方法如何与另一个事务方法交互。Spring 支持以下几种传播行为:

          • REQUIRED(默认值):如果当前没有事务,则创建一个新的事务。如果当前已经存在事务,当前方法将加入到这个事务中。

          • REQUIRES_NEW:无论当前是否存在事务,都会创建一个新的事务。如果当前有事务,则会暂停当前事务。

          • SUPPORTS:如果当前有事务,则加入事务。如果没有事务,则以非事务的方式执行。

          • NOT_SUPPORTED:如果当前有事务,则将事务挂起,并以非事务方式执行。

          • MANDATORY:当前必须有事务。如果当前没有事务,则抛出异常。

          • NEVER:当前不能有事务。如果当前有事务,则抛出异常。

          • NESTED:如果当前没有事务,则创建一个新的事务。如果当前有事务,则创建一个嵌套事务。嵌套事务的提交与回滚会独立于外部事务。

      • 事务隔离级别(Isolation)

        • 事务隔离级别定义了不同事务之间如何隔离。Spring 支持以下几种隔离级别:

          • READ_UNCOMMITTED:允许读取未提交的数据,可能导致脏读、不可重复读、幻读问题。

          • READ_COMMITTED:只能读取已经提交的数据,避免脏读,但可能会有不可重复读和幻读。

          • REPEATABLE_READ:读取的是一致的数据,避免脏读和不可重复读,但可能会有幻读问题。

          • SERIALIZABLE:强制事务串行化,避免脏读、不可重复读和幻读,但性能开销较大。

    • 7.5 事务回滚机制

      • ​​​​​​​​​​​​​​Spring 的事务回滚机制允许我们控制事务在出现异常时是否回滚。默认情况下,Spring 仅在遇到 运行时异常(RuntimeException错误(Error 时回滚事务。

      • 默认回滚规则:

        • 回滚事务:遇到 RuntimeExceptionError

        • 不回滚事务:遇到 checked exceptions(检查型异常)。

  • 8. 配置与优化

    • 8.1 配置数据源(DataSource

      • ​​​​​​​如果你使用的是关系型数据库(如 MySQL、PostgreSQL、H2 等),Spring Boot 会自动配置数据源。

        例如,对于 MySQL,Spring Boot 会自动使用 HikariCP(Spring Boot 默认的数据源连接池)来管理连接池。

    • 8.2 使用 application.properties 配置数据库连接池

      • ​​​​​​​​​​​​​​Spring Boot 默认使用 HikariCP 作为连接池,它是一个高性能的 JDBC 连接池,可以有效地管理数据库连接。在 application.properties 文件中,可以配置数据库连接池的相关属性。

      • 配置连接池的基本参数

        • # 数据源配置
          spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
          spring.datasource.username=root
          spring.datasource.password=root
          spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# 连接池配置
          spring.datasource.hikari.maximum-pool-size=20  # 最大连接池大小
          spring.datasource.hikari.minimum-idle=5       # 最小空闲连接数
          spring.datasource.hikari.idle-timeout=600000 # 空闲连接超时时间(毫秒)
          spring.datasource.hikari.max-lifetime=1800000 # 连接最大生命周期(毫秒)
          spring.datasource.hikari.connection-timeout=30000 # 连接超时时间(毫秒)
          
      • 配置其他连接池特性

        • spring.datasource.hikari.auto-commit=true   # 自动提交事务
          spring.datasource.hikari.connection-test-query=SELECT 1 # 检测连接是否有效的查询语句
          spring.datasource.hikari.pool-name=HikariCP # 连接池名称
          spring.datasource.hikari.leak-detection-threshold=15000 # 设置连接泄露检测时间(毫秒)
          
      • 配置连接池性能优化

        • spring.datasource.hikari.maximum-pool-size:控制最大连接数。根据业务量进行调整,过大或过小都会影响性能。

        • spring.datasource.hikari.minimum-idle:空闲连接数,设置为空闲连接池的最小值。可以帮助快速响应查询请求。

        • spring.datasource.hikari.idle-timeout:空闲连接超时时间,当连接池中的连接空闲时间超过此值时,将被销毁。

        • spring.datasource.hikari.max-lifetime:连接最大生命周期,当连接池中的连接达到此最大生命周期时,它们将被销毁并重新创建。

    • 8.3 配置 JPA 的 Hibernate 属性(如:DDL 自动生成策略、SQL 日志输出等)

      • 8.3.1 ​​​​​​​​​​​​​​配置 Hibernate 的 DDL 自动生成策略

        • spring.jpa.hibernate.ddl-auto:控制 Hibernate 如何自动管理数据库模式。

        • 常见的值包括:

          • none:不进行任何操作,数据库架构由外部管理。

          • update:Hibernate 会根据实体类的变更自动更新数据库架构。

          • create:每次应用启动时都会创建数据库架构。

          • create-drop:在应用启动时创建架构,并在应用关闭时删除架构。

            • spring.jpa.hibernate.ddl-auto=update
              
      • 8.3.2 配置 Hibernate 的 SQL 日志输出

        • spring.jpa.show-sql:控制是否输出 SQL 语句。

        • spring.jpa.properties.hibernate.format_sql:格式化 SQL,使其更易读。

        • spring.jpa.properties.hibernate.use_sql_comments:是否输出 SQL 注释,帮助理解 SQL 执行过程。

          • spring.jpa.show-sql=true
            spring.jpa.properties.hibernate.format_sql=true
            spring.jpa.properties.hibernate.use_sql_comments=true
            

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

商品,订单业务流程梳理一

业务架构梳理 业务系统介绍 业务商品流程 业务订单流程 业务售后流程 系统架构 技术栈

HDR视频技术之二:光电转换与 HDR 图像显示

将自然界中的真实场景转换为屏幕上显示出来的图像&#xff0c;往往需要经过两个主要的步骤&#xff1a;第一个是通过摄影设备&#xff0c;将外界的光信息转换为图像信息存储起来&#xff0c;本质上是存储为数字信号&#xff1b;第二个是通过显示设备&#xff0c;将图像信息转换…

Linux完结

学习视频笔记均来自B站UP主" 泷羽sec",如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 【linux基础之病毒编写&#xff08;完结&#xff09;】 https://www.bilibili.com/video…

苹果iOS 18.4将允许欧盟地区的iPhone用户设置默认地图和翻译应用

在一份最新文件中&#xff0c;苹果概述了其为遵守欧盟数字市场法案所采取的措施&#xff0c;并透露将允许欧盟的 iPhone 和 iPad 用户从"2025 年春季"开始设置默认导航和翻译应用程序。 这一时间表表明&#xff0c;这些选项将在 iOS 18.4 和 iPadOS 18.4 中添加&…

鸿蒙进阶篇-type、typeof、类

“在科技的浪潮中&#xff0c;鸿蒙操作系统宛如一颗璀璨的新星&#xff0c;引领着创新的方向。作为鸿蒙开天组&#xff0c;今天我们将一同踏上鸿蒙基础的探索之旅&#xff0c;为您揭开这一神奇系统的神秘面纱。” 各位小伙伴们我们又见面了,我就是鸿蒙开天组,下面让我们进入今…

鸿蒙进阶篇-剩余和展开、简单和复杂类型

“在科技的浪潮中&#xff0c;鸿蒙操作系统宛如一颗璀璨的新星&#xff0c;引领着创新的方向。作为鸿蒙开天组&#xff0c;今天我们将一同踏上鸿蒙基础的探索之旅&#xff0c;为您揭开这一神奇系统的神秘面纱。” 各位小伙伴们我们又见面了,我就是鸿蒙开天组,下面让我们进入今…

爬虫学习4

from threading import Thread#创建任务 def func(name):for i in range(100):print(name,i)if __name__ __main__:#创建线程t1 Thread(targetfunc,args("1"))t2 Thread(targetfunc, args("2"))t1.start()t2.start()print("我是诛仙剑")from …

【LeetCode:3242. 设计相邻元素求和服务 + 模拟 + 哈希表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

[产品管理-62]:不同角度看产品的生命周期

目录 一、产品的生命周期与不确定性 创意生成 原型开发 规模化和商业化 - 上市前的准备 产品上市 二、产品的生命周期与组合管理 三、产品生命周期变得越来越短的原因 1. 科技进步 2. 消费需求变化 》 物质需求的单一化到精神需求的易变化 3. 市场竞争加剧 4. 全球化…

WPS单元格重复值提示设置

选中要检查的所有的单元格 设置提示效果 当出现单元格值重复时&#xff0c;重复的单元格就会自动变化 要修改或删除&#xff0c;点击

华为eNSP:AAA认证(pap和chap)telnet/ssh

pap模式 一、拓扑图 二、配置过程 1、这个型号路由器是不带串口的&#xff0c;所以需要添加串口板卡 2、加入串行接口卡槽 右击路由&#xff0c;选择设置&#xff0c;将串口板卡拖动到路由器扩展槽&#xff0c;并开机即可 3、认证方路由器配置 [r8]aaa #进入aaa认证 [r8-a…

CSS网格布局:打造现代网页设计的强大工具

在现代网页设计中&#xff0c;布局的灵活性和美观性至关重要。随着需求的不断变化&#xff0c;CSS 网格布局&#xff08;CSS Grid Layout&#xff09;作为一种新兴的布局方式&#xff0c;正在成为开发者们的首选工具。它能够轻松创建复杂的网格结构&#xff0c;使得网页设计更加…

SpringBoot助力的共享汽车业务优化系统

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

算法 -插入排序

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【算法】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 文章目录 &#x1f4a1;插入排序1. ➡️ 直接插入排序&#x1f5bc;️示意图&#x1f4d6;简介&#x1f4a1;实现思路&#x1f4bb;代码实现&#x1f4dd;具体示例 2. ⬆️…

2025中国(郑州)国际台球产业博览会(壹肆柒·台球展)3月

随着体育经济的迅猛发展&#xff0c;台球作为一项受欢迎的竞技运动&#xff0c;近年来在中国逐渐崭露头角。为促进台球产业的发展&#xff0c;推动各类相关产品及服务的交流与合作&#xff0c;从而实现共享共赢&#xff0c;2025年中国&#xff08;郑州&#xff09;国际台球产业…

开放式耳机如何选择?五款千万不能错过的开放式耳机机型推荐

在这里我先做一个行业的知识科普&#xff0c;目前市场上有超过80%的品牌&#xff0c;都是非专业的开放式耳机品牌&#xff0c;也就是跨界大牌或者网红品牌&#xff0c;这些品牌由于没有开放式声学的技术沉淀&#xff0c;在制作开放式耳机的时候&#xff0c;通常都是直接套用传统…

VulkanTutorial(17`Loading models, Mipmaps)

Loading models 我们将使用tinyobjloader库从OBJ文件加载顶点和索引&#xff0c;它速度快&#xff0c;易于集成&#xff0c;因为它是一个像stb_image一样的单一文件库 因为我们没有学习光照&#xff0c;使用照明烘焙的纹理 在程序中添加两个新的配置变量来定义模型和纹理路径&…

DAO模式的理解

目录 DAO模式 含义 DAO模式 的理解 分层思维 分层含义 分层目的 dao层 dao包&#xff08;对接的是操作数据库的接口&#xff09; dao包下lmpl 包&#xff08;dao包中接口的实现类&#xff09; 补充 1 你创建的实体类需要和数据库中建的表一一对应。 总结 DAO模式 含义…

大健康零售行业帮助中心的构建与客户服务优化

在大健康零售行业&#xff0c;客户服务的质量直接影响着企业的品牌形象和市场竞争力。随着数字化转型的推进&#xff0c;构建一个高效、智能的帮助中心成为了提升客户服务和满意度的关键。本文将分析大健康零售行业如何通过构建帮助中心来优化客户服务&#xff0c;并提升客户满…

【JWT】Asp.Net Core中JWT刷新Token解决方案

Asp.Net Core中JWT刷新Token解决方案 前言方案一:当我们操作某个需要token作为请求头的接口时,返回的数据错误error.response.status === 401,说明我们的token已经过期了。方案二:实现用户无感知的刷新token值,我们希望当响应返回的数据是401身份过期时,响应阻拦器自动帮我…