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

news2024/11/13 11:30:33

目录

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=UTC
                username: root
                password: root
                driver-class-name: com.mysql.cj.jdbc.Driver
            
              jpa:
                hibernate:
                  ddl-auto: update
                show-sql: true
                database-platform: org.hibernate.dialect.MySQL5Dialect
            
              hikari:
                maximum-pool-size: 10
                minimum-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;
            }
        
            @Override
            public 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 字段映射到 Order
              private 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 {
        
            @Autowired
            private 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 {
        
            @Autowired
            private UserRepository userRepository;  // 注入 UserRepository
        
            @Autowired
            private 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.coloradmin.cn/o/2237487.html

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

相关文章

MQTT协议解析 : 物联网领域的最佳选择

1. MQTT协议概述 1.1 MQTT协议是什么 MQTT : Message Queuing Telemetry Transport 模式 : 发布 / 订阅主题优点 : 代码量小、低带宽、实时可靠应用 : 物联网、小型设备、移动应用MQTT 常用端口 : 1883 MQTT是一个网络协议&#xff0c;和HTTP类似&#xff0c;因为轻量简单&…

Pytorch实现transformer语言模型

转载自&#xff1a;| 03_language_model/02_Transformer语言模型.ipynb | 从头训练Transformer语言模型 |Open In Colab | Transformer语言模型 本节训练一个 sequence-to-sequence 模型&#xff0c;使用pytorch的 nn.Transformer <https://pytorch.org/docs/master/nn.ht…

ElasticSearch向量检索技术方案介绍

1、背景 在人工智能快速发展的今天&#xff0c;推荐技术、以文搜图、以文搜视频、以图搜图等技术已经得到了广泛的应用&#xff0c;在百度、小红书、抖音、快手等app上随便输入一段文本&#xff0c;搜索结果已不像早些年那么单一&#xff1a;只有一些文字信息&#xff0c;现在的…

算法(第一周)

一周周五&#xff0c;总结一下本周的算法学习&#xff0c;从本周开始重新学习许久未见的算法&#xff0c;当然不同于大一时使用的 C 语言以及做过的简单题&#xff0c;现在是每天一题 C 和 JavaScript&#xff08;还在学&#xff0c;目前只写了一题&#xff09; 题单是代码随想…

华为云镜像仓库基本操作

1. 登陆华为云账户,在搜索框输入"镜像容器",如下图所示: 单击 输入名称后单击确定 创建成功 2. 回到这里 单击这里 获得登陆指令 复制到你的云服务器粘贴,回车后提示"Login Succeeded"表示登陆成功. 3. 还是在"总览"这里,单击这里 跟着复制操作…

【1个月速成Java】基于Android平台开发个人记账app学习日记——第10天,登录状态保持与退出登录

系列专栏链接如下&#xff0c;方便跟进&#xff1a; https://blog.csdn.net/weixin_62588253/category_12821860.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12821860&sharereferPC&sharesourceweixin_62588253&sharefromfrom_linkhttps://b…

MySQL系列之如何在Linux只安装客户端

导览 前言Q&#xff1a;如何安装一个Linux环境下的MySQL客户端一、准备文件1. 确认Server版本2. 选择Client安装文件 二、下载并安装1. 下载1.1 寻找文件1.2 文件说明 2. 安装2.1 上传至Linux服务器2.2 执行安装 三、连接验证1. 确认远程授权2. 建立远程连接 结语精彩回放 前言…

arcgis pro 学习笔记

二维三维集合在一起&#xff0c;与arcgis不同 一、首次使用&#xff0c;几个基本设置 1.选项——常规里面设置自动保存时间 2.新建工程文件&#xff0c;会自动加载地图&#xff0c;可以在选项里面设置为无&#xff0c;以提高启动效率。 3.设置缓存位置&#xff0c;可勾选每次…

【论文复现】MSA+抑郁症模型总结(三)

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀MSA抑郁症模型 热门研究领域&#xff1a;情感计算的横向发展1. 概述2. 论文地址3. 研究背景4. 主要贡献5. 模型结构和代码6. 数据集介绍7. 性…

‌STAR法则

一&#xff1a;STAR法则 STAR法则是一种简单而实用的表现技巧&#xff0c;常被用于求职过程中的个人经历描述&#xff0c;富有条理性&#xff0c;可以帮助你在职场中脱颖而出。“STAR”分别对应的是situation-task-action-result&#xff0c;通过情境、目标、行动和结果四个方面…

java:使用Multi-Release Jar改造Java 1.7项目增加module-info.class以全面合规Java 9模块化规范

common-java是一个我维护了好多年的一个基础项目,编译目标为Java 1.7 现在整个团队的项目要做Java 9以上的技术迁移准备,就需要对这个在内部各项目中被广泛引用的基础项目进行改造,以适合Java 9的模块化规范。 Automatic-Module-Name Java 9的模块化规范(即Java Platform Mod…

力扣题库——75.颜色分类

这道题采用三路快速排序&#xff0c;快速排序思路看这里快速排序。将数列分为三组&#xff1a;小于基准、等于基准、大于基准。和快排一样&#xff0c;对左右递归进行快速排序。 先将题目简化&#xff0c;如果只有数字0和1&#xff0c;扫描一遍数组&#xff0c;遇到数字1不用管…

python - leetcode【数据结构-算法】-入门/通关手册

python的算法入门/通关/手册 前言&#xff1a;算法通关手册&#xff08;LeetCode&#xff09;-githubHello 算法&#xff1a;python数据结构和算法 - 中文版The Algorithms - Python最后刷题思维: python-leetcode刷题常用语法&#xff1a;变量定义&#xff1a;逻辑与或非和按位…

使用 Flask 和 ONLYOFFICE 实现文档在线编辑功能

提示&#xff1a;CSDN 博主测评ONLYOFFICE 文章目录 引言技术栈环境准备安装 ONLYOFFICE 文档服务器获取 API 密钥安装 Flask 和 Requests 创建 Flask 应用项目结构编写 app.py创建模板 templates/index.html 运行应用功能详解文档上传生成编辑器 URL显示编辑器回调处理 安全性…

EasyUI弹出框行编辑,通过下拉框实现内容联动

EasyUI弹出框行编辑&#xff0c;通过下拉框实现内容联动 需求 实现用户支付方式配置&#xff0c;当弹出框加载出来的时候&#xff0c;显示用户现有的支付方式&#xff0c;datagrid的第一列为conbobox,下来选择之后实现后面的数据直接填充&#xff1b; 点击新增&#xff1a;新…

C# 选择导入文件的路径、导出文件的路径

通过C#代码&#xff0c;调出windows风格的文件选择对话框和存储文件对话框。提供界面来选择文件的位置&#xff0c;并将完整路径以字符串形式返回。 1、选择导入文件&#xff0c;获取其路径 C#通过这段代码将弹出一个文件选择对话框&#xff0c;允许用户选择一个文件&#xff…

数据结构-并查集专题(1)

一、前言 因为要开始准备年底的校赛和明年年初的ACM、蓝桥杯、天梯赛&#xff0c;于是开始按专题梳理一下对应的知识点&#xff0c;先从简单入门又值得记录的内容开始&#xff0c;并查集首当其冲。 二、我的模板 虽然说是借用了jiangly鸽鸽的板子&#xff0c;但是自己也小做…

二手交易平台测试用例设计和执行

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;追求开源思想和学无止境思想一直在提升技术的路上 &#x1f384; &#x1f308;涉及的领域有&#xff1a;Java、Python、微服务架构和分布式架构思想、基本算法编程&#x1f308; &#x1f386;喜欢的朋友可…

计算机图形学论文 | 多边形中的点可见性快速算法

&#x1f98c;&#x1f98c;&#x1f98c;读论文 &#x1f428;&#x1f428;摘要 针对点的可见性计算这一计算几何中的基础问题&#xff0c;提出一种支持任意查询点的可见多边形快速计算的基于多边形Voronoi图的点可见性算法。以与Voronoi骨架路径对应的Voronoi通道概念&…

Redis 高并发分布式锁实战

目录 环境准备 一 . Redis 安装 二&#xff1a;Spring boot 项目准备 三&#xff1a;nginx 安装 四&#xff1a;Jmeter 下载和配置 案例实战 优化一&#xff1a;加 synchronized 锁 优化二&#xff1a;使用 redis 的 setnx 实现分布式锁 优化三&#xff1a;使用 Lua 脚本…