十三:java web(5)-- Spring数据持久层

目录

Spring 数据持久层

1. Spring 与 JDBC

1.1 使用 Spring 管理数据库连接

1.1.2 Apache Commons DBCP 基于配置文件xml 使用

1.1.3 Apache Commons DBCP 基于配置类使用

1.1.4 HikariCP 基于配置文件xml 使用 推荐使用 Spring Boot 默认连接池

1.1.5 HikariCP 基于配置类 使用

1.2 JdbcTemplate 的使用

1.2.1 DataSource 注入到 JdbcTemplate 基于xml方式

1.2.2 DataSource 注入到 JdbcTemplate 基于配置类方式

1.2.3 JdbcTemplate 基本操作  感觉了解就好 

1.3 总结:

2. Spring 与 ORM 框架

2.1 ORM框架是什么

2.2 集成 MyBatis 

基于xml 配置的方式 前提是你连接池可以连接上你数据库

2.2.1 引入pom.xml

2.2.2 编写配置文件 applicationContext.xml

2.2.3 编写实体类

2.2.4 编写mapper接口

2.2.5 编写mapper.xml

2.2.6 在使用的类 注入mapper类

2.2.7 主函数调用

3. 事务管理

3.1 事务管理的基础概念

3.2 声明式事务管理(@Transactional)

3.3 编程式事务管理


Spring 数据持久层

  • 1. Spring 与 JDBC

    • 1.1 使用 Spring 管理数据库连接

      • 1.1.1 Spring 提供了数据源(DataSource)的管理方式,通过将数据库连接池配置为一个 Spring Bean,Spring 可以帮助我们管理连接的创建与销毁。常用的数据源有:

        • DriverManagerDataSource:仅适用于测试环境,因为它不使用连接池。
        • Apache Commons DBCP:提供了基本的连接池功能。
        • HikariCP:高性能的连接池管理器。
      • 1.1.2 Apache Commons DBCP 基于配置文件xml 使用
        • pom.xml
          •         <dependency>
                        <groupId>org.apache.commons</groupId>
                        <artifactId>commons-dbcp2</artifactId>
                        <version>2.9.0</version>
                    </dependency>
            
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.33</version>
                    </dependency>
        • 配置文件 applicationContext.xml
          • <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
                   xsi:schemaLocation="http://www.springframework.org/schema/beans
                                       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
            
                <!--    applicationContext.xml 是 Spring 框架中的配置文件,
                通常用于定义 Spring IoC(控制反转)容器中的 Bean 配置和管理。
                这个文件主要用于将 Spring 的配置项和组件描述清楚,
                告知 Spring 容器如何实例化、配置和管理应用程序中的各种对象(Bean)。
                它是 Spring 配置的传统方式之一(除了注解和 Java 配置类)。-->
            
                <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
                    <!-- 数据库驱动类 -->
                    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
            
                    <!-- 数据库连接 URL -->
                    <property name="url" value="jdbc:mysql://localhost:3306/lirui" />
            
                    <!-- 数据库用户名 -->
                    <property name="username" value="root" />
            
                    <!-- 数据库密码 -->
                    <property name="password" value="root" />
                    <!-- 可选的连接池参数 -->
                    <!-- 初始连接数 -->
                    <property name="initialSize" value="5" />
                    <!-- 最大连接数 -->
                    <property name="maxTotal" value="20" />
                    <!-- 最小空闲连接数 -->
                    <property name="minIdle" value="5" />
                    <!-- 最大空闲连接数 -->
                    <property name="maxIdle" value="10" />
                    <!-- 最大等待时间(毫秒),连接池用尽时的等待时长 -->
                    <property name="maxWaitMillis" value="10000" />
                </bean>
            
                <!-- 配置 Engine Bean,带参数构造函数 -->
                <bean id="engine" class="com.lirui.car.Engine">
                    <constructor-arg value="V8" />
                </bean>
            
                <!-- 配置 GPS Bean -->
                <bean id="gps" class="com.lirui.car.GPSImpl" />
            
                <!-- 配置 Radio Bean -->
                <bean id="radio" class="com.lirui.car.RadioImpl" />
            
                <!-- 配置 Car Bean,使用 setter 注入 -->
                <bean id="car" class="com.lirui.car.Car">
                    <property name="engine" ref="engine" />
                    <property name="gps" ref="gps" />
                    <property name="radio" ref="radio" />
                    <property name="dataSource" ref="dataSource" />
                </bean>
            
            
            </beans>
            
        • 调用
          • package com.lirui.car;
            
            
            import org.springframework.beans.factory.annotation.Autowired;
            
            import javax.sql.DataSource;
            import java.sql.Connection;
            import java.sql.PreparedStatement;
            import java.sql.ResultSet;
            import java.sql.SQLException;
            
            
            public class Car {
                private Engine engine;
                private GPS gps;
                private Radio radio;
                private DataSource dataSource;
            
            
                // Setters for dependency injection
                public void setEngine(Engine engine) {
                    this.engine = engine;
                }
            
                public void setGps(GPS gps) {
                    this.gps = gps;
                }
            
                public void setRadio(Radio radio) {
                    this.radio = radio;
                }
            
                public void setDataSource(DataSource dataSource) {
                    this.dataSource = dataSource;
                }
            
                public void drive() {
                    // 使用 DataSource 获取数据库连接并执行查询
                    String sql = "SELECT id, ui_path, menu_type FROM t_sys_resource";
                    try (Connection connection = dataSource.getConnection();
                         PreparedStatement statement = connection.prepareStatement(sql);
                         ResultSet resultSet = statement.executeQuery()) {
            
                        // 遍历查询结果
                        while (resultSet.next()) {
                            int id = resultSet.getInt("id");
                            String name = resultSet.getString("ui_path");
                            String email = resultSet.getString("menu_type");
            
                            System.out.println("ID: " + id + ", ui_path: " + name + ", menu_type: " + email);
                        }
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    System.out.println("引擎"+engine.getType() );
                    gps.navigate();
                    radio.playMusic();
                }
            }
            
        • 主函数
          •     public static void main(String[] args) {
                    // 加载 Spring 配置文件
                    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            
                    // 获取 userService Bean
                    Car car = context.getBean("car", Car.class);
            
                    // 调用方法
                    car.drive();
                }

      • 1.1.3 Apache Commons DBCP 基于配置类使用
        • pom.xml

          •         <dependency>
                        <groupId>org.apache.commons</groupId>
                        <artifactId>commons-dbcp2</artifactId>
                        <version>2.9.0</version>
                    </dependency>
            
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.33</version>
                    </dependency>
        • application.properties

          • db.url=jdbc:mysql://localhost:3306/lirui
            db.username=root
            db.password=root
            db.driverClassName=com.mysql.cj.jdbc.Driver
            
        • config配置文件

          • package com.lirui.carconfig;
            
            
            import org.apache.commons.dbcp2.BasicDataSource;
            import org.springframework.beans.factory.annotation.Value;
            import org.springframework.context.annotation.*;
            
            import javax.sql.DataSource;
            
            @Configuration
            @ComponentScan(basePackages = "com.lirui.carconfig")
            @PropertySource("classpath:application.properties")
            @EnableAspectJAutoProxy
            public class AppConfig {
            
                @Value("${db.url}")
                private String dbUrl;
            
                @Value("${db.username}")
                private String dbUsername;
            
                @Value("${db.password}")
                private String dbPassword;
            
                @Value("${db.driverClassName}")
                private String driverClassName;
            
                @Bean
                public DataSource dataSource() {
                    BasicDataSource dataSource = new BasicDataSource();
                    dataSource.setDriverClassName(driverClassName);
                    dataSource.setUrl(dbUrl);
                    dataSource.setUsername(dbUsername);
                    dataSource.setPassword(dbPassword);
            
                    dataSource.setInitialSize(5);
                    dataSource.setMaxTotal(20);
                    dataSource.setMinIdle(5);
                    dataSource.setMaxIdle(10);
                    dataSource.setMaxWaitMillis(10000);
            
                    return dataSource;
                }
            
                @Bean
                public Engine engine() {
                    return new Engine("V8");
                }
            
                @Bean
                public GPS gps() {
                    return new GPSImpl();
                }
            
                @Bean
                public Radio radio() {
                    return new RadioImpl();
                }
            
                @Bean
                public Car car() {
                    Car car = new Car();
                    car.setEngine(engine());
                    car.setGps(gps());
                    car.setRadio(radio());
                    car.setDataSource(dataSource());
                    return car;
                }
            }
        • 调用

          • package com.lirui.carconfig;
            
            
            import org.springframework.beans.factory.annotation.Autowired;
            
            import javax.sql.DataSource;
            import java.sql.Connection;
            import java.sql.PreparedStatement;
            import java.sql.ResultSet;
            import java.sql.SQLException;
            
            
            public class Car {
                private Engine engine;
                private GPS gps;
                private Radio radio;
                private DataSource dataSource;
            
            
                public void setEngine(Engine engine) {
                    this.engine = engine;
                }
            
                public void setGps(GPS gps) {
                    this.gps = gps;
                }
            
                public void setRadio(Radio radio) {
                    this.radio = radio;
                }
            
                public void setDataSource(DataSource dataSource) {
                    this.dataSource = dataSource;
                }
            
            
                public void drive() {
                    // 使用 DataSource 获取数据库连接并执行查询
                    String sql = "SELECT id, ui_path, menu_type FROM t_sys_resource";
                    try (Connection connection = dataSource.getConnection();
                         PreparedStatement statement = connection.prepareStatement(sql);
                         ResultSet resultSet = statement.executeQuery()) {
            
                        // 遍历查询结果
                        while (resultSet.next()) {
                            int id = resultSet.getInt("id");
                            String name = resultSet.getString("ui_path");
                            String email = resultSet.getString("menu_type");
            
                            System.out.println("ID: " + id + ", ui_path: " + name + ", menu_type: " + email);
                        }
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    System.out.println("引擎" + engine.getType());
                    gps.navigate();
                    radio.playMusic();
                }
            }
            
        • 主函数

          • package com.lirui.carconfig;
            
            import org.springframework.context.ApplicationContext;
            import org.springframework.context.annotation.AnnotationConfigApplicationContext;
            import org.springframework.context.support.ClassPathXmlApplicationContext;
            
            public class Main {
            
                public static void main(String[] args) {
                    // 使用 Java 配置类来初始化 Spring 容器
                    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            
                // 获取 Car 实例,依赖项会自动注入
                    Car car = context.getBean(Car.class);
                    car.drive();
            
                    context.close();
                }
            }
            

      • 1.1.4 HikariCP 基于配置文件xml 使用 推荐使用 Spring Boot 默认连接池
        • pom.xml (1.8版本 选3.x  11及以上 5.x)
          •         <!-- HikariCP 连接池依赖 -->
                    <dependency>
                        <groupId>com.zaxxer</groupId>
                        <artifactId>HikariCP</artifactId>
                        <version>3.4.5</version>
                    </dependency>
            
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.33</version>
                    </dependency>
        • 配置文件 applicationContext.xml
          • <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
                   xsi:schemaLocation="http://www.springframework.org/schema/beans
                                       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
            
                <!--    applicationContext.xml 是 Spring 框架中的配置文件,
                通常用于定义 Spring IoC(控制反转)容器中的 Bean 配置和管理。
                这个文件主要用于将 Spring 的配置项和组件描述清楚,
                告知 Spring 容器如何实例化、配置和管理应用程序中的各种对象(Bean)。
                它是 Spring 配置的传统方式之一(除了注解和 Java 配置类)。-->
            
                <!-- HikariCP 配置 -->
                <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
                    <!-- 设置数据库连接池配置 -->
                    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/lirui?useSSL=false&amp;serverTimezone=UTC"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
            
                    <!-- HikariCP 连接池相关参数 -->
                    <property name="maximumPoolSize" value="10"/> <!-- 最大连接数 -->
                    <property name="minimumIdle" value="5"/>     <!-- 最小空闲连接数 -->
                    <property name="connectionTimeout" value="30000"/> <!-- 连接超时(毫秒) -->
                    <property name="idleTimeout" value="600000"/> <!-- 空闲连接超时(毫秒) -->
                    <property name="maxLifetime" value="1800000"/> <!-- 连接最大生命周期(毫秒) -->
                </bean>
            
                <!-- 配置 Engine Bean,带参数构造函数 -->
                <bean id="engine" class="com.lirui.car.Engine">
                    <constructor-arg value="V8" />
                </bean>
            
                <!-- 配置 GPS Bean -->
                <bean id="gps" class="com.lirui.car.GPSImpl" />
            
                <!-- 配置 Radio Bean -->
                <bean id="radio" class="com.lirui.car.RadioImpl" />
            
                <!-- 配置 Car Bean,使用 setter 注入 -->
                <bean id="car" class="com.lirui.car.Car">
                    <property name="engine" ref="engine" />
                    <property name="gps" ref="gps" />
                    <property name="radio" ref="radio" />
                    <property name="dataSource" ref="dataSource" />
                </bean>
            
            
            </beans>
            
        • sql调用函数
          • package com.lirui.car;
            
            
            import javax.sql.DataSource;
            import java.sql.Connection;
            import java.sql.PreparedStatement;
            import java.sql.ResultSet;
            import java.sql.SQLException;
            
            
            public class Car {
                private Engine engine;
                private GPS gps;
                private Radio radio;
                private DataSource dataSource;
            
            
                // Setters for dependency injection
                public void setEngine(Engine engine) {
                    this.engine = engine;
                }
            
                public void setGps(GPS gps) {
                    this.gps = gps;
                }
            
                public void setRadio(Radio radio) {
                    this.radio = radio;
                }
            
                public void setDataSource(DataSource dataSource) {
                    this.dataSource = dataSource;
                }
            
                public void drive() {
                    // 使用 DataSource 获取数据库连接并执行查询
                    String sql = "SELECT id, ui_path, menu_type FROM t_sys_resource";
                    try (Connection connection = dataSource.getConnection();
                         PreparedStatement statement = connection.prepareStatement(sql);
                         ResultSet resultSet = statement.executeQuery()) {
            
                        // 遍历查询结果
                        while (resultSet.next()) {
                            int id = resultSet.getInt("id");
                            String name = resultSet.getString("ui_path");
                            String email = resultSet.getString("menu_type");
            
                            System.out.println("ID: " + id + ", ui_path: " + name + ", menu_type: " + email);
                        }
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    System.out.println("引擎"+engine.getType() );
                    gps.navigate();
                    radio.playMusic();
                }
            }
            
        • 主函数
          • package com.lirui.car;
            
            import com.lirui.example.UserService;
            import org.springframework.context.ApplicationContext;
            import org.springframework.context.annotation.AnnotationConfigApplicationContext;
            import org.springframework.context.support.ClassPathXmlApplicationContext;
            
            public class Main {
            
                public static void main(String[] args) {
                    // 加载 Spring 配置文件
                    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            
                    // 获取 userService Bean
                    Car car = context.getBean("car", Car.class);
            
                    // 调用方法
                    car.drive();
                }
            }
            

      • 1.1.5 HikariCP 基于配置类 使用
        • 和DBCP 差不多样的用法  改一下就可以了
        • package com.lirui.carconfig;
          
          
          import com.zaxxer.hikari.HikariConfig;
          import com.zaxxer.hikari.HikariDataSource;
          import org.apache.commons.dbcp2.BasicDataSource;
          import org.springframework.beans.factory.annotation.Value;
          import org.springframework.context.annotation.*;
          
          import javax.sql.DataSource;
          
          @Configuration
          @ComponentScan(basePackages = "com.lirui.carconfig")
          @PropertySource("classpath:application.properties")
          @EnableAspectJAutoProxy
          public class AppConfig {
          
          
              @Bean
              public DataSource dataSource() {
                  HikariConfig hikariConfig = new HikariConfig();
          
                  // 数据库连接信息
                  hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
                  hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/lirui?useSSL=false&serverTimezone=UTC");
                  hikariConfig.setUsername("root");
                  hikariConfig.setPassword("root");
          
                  // HikariCP 连接池设置
                  hikariConfig.setMaximumPoolSize(10);      // 最大连接数
                  hikariConfig.setMinimumIdle(5);           // 最小空闲连接数
                  hikariConfig.setConnectionTimeout(30000); // 连接超时(毫秒)
                  hikariConfig.setIdleTimeout(600000);      // 空闲连接超时(毫秒)
                  hikariConfig.setMaxLifetime(1800000);     // 最大连接生命周期(毫秒)
          
                  return new HikariDataSource(hikariConfig);
              }
          
              @Bean
              public Engine engine() {
                  return new Engine("V8");
              }
          
              @Bean
              public GPS gps() {
                  return new GPSImpl();
              }
          
              @Bean
              public Radio radio() {
                  return new RadioImpl();
              }
          
              @Bean
              public Car car() {
                  Car car = new Car();
                  car.setEngine(engine());
                  car.setGps(gps());
                  car.setRadio(radio());
                  car.setDataSource(dataSource());
                  return car;
              }
          }

    • 1.2 JdbcTemplate 的使用

      • JdbcTemplate 是 Spring 提供的简化数据库操作的工具类,能帮助我们避免繁琐的资源管理代码,如连接获取与关闭等。我们只需将 DataSource 注入到 JdbcTemplate 中即可。后面所有的演示就用HikariCP 连接池了

      • 1.2.1 DataSource 注入到 JdbcTemplate 基于xml方式
        • 演示的内容还是根据前面代码修改的哈

        • pom.xml

          •         <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-jdbc</artifactId>
                        <version>5.0.9.RELEASE</version>
                    </dependency>
            
                    <!-- HikariCP 连接池依赖 -->
                    <dependency>
                        <groupId>com.zaxxer</groupId>
                        <artifactId>HikariCP</artifactId>
                        <version>3.4.5</version>
                    </dependency>
            
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.33</version>
                    </dependency>
            
        • applicationContext.xml  原来是直接把dataSource 注入到car类中去 现在是先把dataSource 注入到jdbc 然后将jdbc注入car类中

          • <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
                   xsi:schemaLocation="http://www.springframework.org/schema/beans
                                       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
            
                <!--    applicationContext.xml 是 Spring 框架中的配置文件,
                通常用于定义 Spring IoC(控制反转)容器中的 Bean 配置和管理。
                这个文件主要用于将 Spring 的配置项和组件描述清楚,
                告知 Spring 容器如何实例化、配置和管理应用程序中的各种对象(Bean)。
                它是 Spring 配置的传统方式之一(除了注解和 Java 配置类)。-->
            
                <!-- HikariCP 配置 -->
                <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
                    <!-- 设置数据库连接池配置 -->
                    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/lirui?useSSL=false&amp;serverTimezone=UTC"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
            
                    <!-- HikariCP 连接池相关参数 -->
                    <property name="maximumPoolSize" value="10"/> <!-- 最大连接数 -->
                    <property name="minimumIdle" value="5"/>     <!-- 最小空闲连接数 -->
                    <property name="connectionTimeout" value="30000"/> <!-- 连接超时(毫秒) -->
                    <property name="idleTimeout" value="600000"/> <!-- 空闲连接超时(毫秒) -->
                    <property name="maxLifetime" value="1800000"/> <!-- 连接最大生命周期(毫秒) -->
                </bean>
            
                <!-- 配置 Engine Bean,带参数构造函数 -->
                <bean id="engine" class="com.lirui.car.Engine">
                    <constructor-arg value="V8" />
                </bean>
            
                <!-- 配置 GPS Bean -->
                <bean id="gps" class="com.lirui.car.GPSImpl" />
            
                <!-- 配置 Radio Bean -->
                <bean id="radio" class="com.lirui.car.RadioImpl" />
            
                <!-- 配置 Car Bean,使用 setter 注入 -->
                <bean id="car" class="com.lirui.car.Car">
                    <property name="engine" ref="engine" />
                    <property name="gps" ref="gps" />
                    <property name="radio" ref="radio" />
                    <property name="jdbcTemplate" ref="jdbcTemplate" />
                </bean>
            
                <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                    <constructor-arg ref="dataSource" />
                </bean>
            
            
            </beans>
            
        • 调用函数

          • package com.lirui.carconfig;
            
            
            import org.springframework.beans.factory.annotation.Autowired;
            
            import javax.sql.DataSource;
            import java.sql.Connection;
            import java.sql.PreparedStatement;
            import java.sql.ResultSet;
            import java.sql.SQLException;
            
            
            public class Car {
                private Engine engine;
                private GPS gps;
                private Radio radio;
                private DataSource dataSource;
            
            
                public void setEngine(Engine engine) {
                    this.engine = engine;
                }
            
                public void setGps(GPS gps) {
                    this.gps = gps;
                }
            
                public void setRadio(Radio radio) {
                    this.radio = radio;
                }
            
                public void setDataSource(DataSource dataSource) {
                    this.dataSource = dataSource;
                }
            
            
                public void drive() {
                    // 使用 DataSource 获取数据库连接并执行查询
                    String sql = "SELECT id, ui_path, menu_type FROM t_sys_resource";
                    try (Connection connection = dataSource.getConnection();
                         PreparedStatement statement = connection.prepareStatement(sql);
                         ResultSet resultSet = statement.executeQuery()) {
            
                        // 遍历查询结果
                        while (resultSet.next()) {
                            int id = resultSet.getInt("id");
                            String name = resultSet.getString("ui_path");
                            String email = resultSet.getString("menu_type");
            
                            System.out.println("ID: " + id + ", ui_path: " + name + ", menu_type: " + email);
                        }
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    System.out.println("引擎" + engine.getType());
                    gps.navigate();
                    radio.playMusic();
                }
            }
            
        • 主函数

          • package com.lirui.carconfig;
            
            import org.springframework.context.ApplicationContext;
            import org.springframework.context.annotation.AnnotationConfigApplicationContext;
            import org.springframework.context.support.ClassPathXmlApplicationContext;
            
            public class Main {
            
                public static void main(String[] args) {
                    // 使用 Java 配置类来初始化 Spring 容器
                    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            
                // 获取 Car 实例,依赖项会自动注入
                    Car car = context.getBean(Car.class);
                    car.drive();
            
                    context.close();
                }
            }
            
      • 1.2.2 DataSource 注入到 JdbcTemplate 基于配置类方式
        • 配置类
          • package com.lirui.carconfig;
            
            
            import com.zaxxer.hikari.HikariConfig;
            import com.zaxxer.hikari.HikariDataSource;
            import org.apache.commons.dbcp2.BasicDataSource;
            import org.springframework.beans.factory.annotation.Value;
            import org.springframework.context.annotation.*;
            import org.springframework.jdbc.core.JdbcTemplate;
            
            import javax.sql.DataSource;
            
            @Configuration
            @ComponentScan(basePackages = "com.lirui.carconfig")
            @PropertySource("classpath:application.properties")
            @EnableAspectJAutoProxy
            public class AppConfig {
            
                @Value("${db.url}")
                private String dbUrl;
            
            
                @Bean
                public DataSource dataSource() {
                    HikariConfig hikariConfig = new HikariConfig();
            
                    // 数据库连接信息
                    hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
                    hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/lirui?useSSL=false&serverTimezone=UTC");
                    hikariConfig.setUsername("root");
                    hikariConfig.setPassword("root");
            
                    // HikariCP 连接池设置
                    hikariConfig.setMaximumPoolSize(10);      // 最大连接数
                    hikariConfig.setMinimumIdle(5);           // 最小空闲连接数
                    hikariConfig.setConnectionTimeout(30000); // 连接超时(毫秒)
                    hikariConfig.setIdleTimeout(600000);      // 空闲连接超时(毫秒)
                    hikariConfig.setMaxLifetime(1800000);     // 最大连接生命周期(毫秒)
            
                    return new HikariDataSource(hikariConfig);
                }
            
                @Bean
                public JdbcTemplate jdbcTemplate(DataSource dataSource) {
                    return new JdbcTemplate(dataSource);  // 将 DataSource 注入 JdbcTemplate
                }
            
                @Bean
                public Engine engine() {
                    return new Engine("V8");
                }
            
                @Bean
                public GPS gps() {
                    return new GPSImpl();
                }
            
                @Bean
                public Radio radio() {
                    return new RadioImpl();
                }
            
                @Bean
                public Car car() {
                    Car car = new Car();
                    car.setEngine(engine());
                    car.setGps(gps());
                    car.setRadio(radio());
                    return car;
                }
            }
        • 主类
          • package com.lirui.carconfig;
            
            import org.springframework.context.ApplicationContext;
            import org.springframework.context.annotation.AnnotationConfigApplicationContext;
            import org.springframework.context.support.ClassPathXmlApplicationContext;
            
            public class Main {
            
                public static void main(String[] args) {
                    // 使用 Java 配置类来初始化 Spring 容器
                    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            
                // 获取 Car 实例,依赖项会自动注入
                    Car car = context.getBean(Car.class);
                    car.drive();
            
                    context.close();
                }
            }
            

        • 1.2.3 JdbcTemplate 基本操作  感觉了解就好 
          • 增、删、改操作
            • update(String sql):执行插入、更新或删除操作。
            • update(String sql, Object... args):带参数的增、删、改操作。
            • String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
              jdbcTemplate.update(sql, "张三", 25);
              
          • 查询单个值
            • queryForObject(String sql, Class<T> requiredType):查询单个结果,例如获取记录总数。
            • queryForObject(String sql, Object[] args, Class<T> requiredType):带参数的查询单个值。
            • String sql = "SELECT COUNT(*) FROM users";
              int count = jdbcTemplate.queryForObject(sql, Integer.class);
              
          • 查询单行数据
            • queryForObject(String sql, RowMapper<T> rowMapper):查询并返回一行数据。
            • queryForObject(String sql, Object[] args, RowMapper<T> rowMapper):带参数的单行查询。
            • String sql = "SELECT * FROM users WHERE id = ?";
              User user = jdbcTemplate.queryForObject(sql, new Object[]{1}, new BeanPropertyRowMapper<>(User.class));
              
          • 查询多行数据
            • query(String sql, RowMapper<T> rowMapper):查询多行数据。
            • query(String sql, Object[] args, RowMapper<T> rowMapper):带参数的多行查询。
            • String sql = "SELECT * FROM users";
              List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
              
          • 批量更新
            • batchUpdate(String sql, List<Object[]> batchArgs):批量操作。
            • String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
              List<Object[]> batchArgs = Arrays.asList(
                  new Object[]{"张三", 28},
                  new Object[]{"李四", 23},
                  new Object[]{"王五", 29}
              );
              jdbcTemplate.batchUpdate(sql, batchArgs);
              
          • 事务管理
            • 在使用 JdbcTemplate 进行数据库操作时,Spring 的事务管理框架可以确保一组数据库操作要么全部成功,要么全部回滚。Spring 支持声明式事务管理,可以通过 @Transactional 注解来管理事务。
            • @Service
              public class UserService {
              
                  @Autowired
                  private JdbcTemplate jdbcTemplate;
              
                  @Transactional
                  public void createUser(User user) {
                      String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
                      jdbcTemplate.update(sql, user.getName(), user.getAge());
                  }
              }
    • 1.3 总结:

      • MySQL:关系型数据库,提供 JDBC 驱动程序让 Java 应用程序可以与它连接。

      • JDBC 驱动:MySQL 提供 com.mysql.cj.jdbc.Driver 驱动,让 Java 可以通过 JDBC 与 MySQL 进行交互。

      • 数据库连接池

        • DBCP2HikariCP 都是连接池实现,负责管理数据库连接。

        • 连接池的目的是提高性能,避免每次数据库操作都创建和销毁连接。

      • 优化

        • HikariCP:提供更高性能的连接池,减少连接获取和释放的延迟,是当前推荐的连接池。

        • DBCP2:是另一个常用的连接池,性能稍逊于 HikariCP,但依然可靠。

      • Spring JDBC

        • 提供简化的数据库操作,利用 JdbcTemplate 简化查询、插入等操作。

        • DBCP2HikariCP 配合使用,通过 DataSource 获取数据库连接池中的连接。

      • 关系:

        • MySQL → 提供数据库和 JDBC 驱动。

        • JDBC 驱动 → 让 Java 可以连接到 MySQL。

        • DBCP2 / HikariCP → 管理与 MySQL 的连接池,提高连接效率。

        • Spring JDBC → 通过 JdbcTemplate 简化与 MySQL 的数据库交互。

  • 2. Spring 与 ORM 框架

    • 2.1 ORM框架是什么

      • ORM 的基本概念

        • ORM 的核心思想是将对象模型与关系数据库的表结构映射在一起,使得数据库的操作能够像操作对象一样进行。通过 ORM,开发人员可以使用对象的属性(而非 SQL 查询语句)来进行增、删、改、查等操作。ORM 框架负责将对象的数据转换成 SQL 查询语句,并将查询结果映射回对象。

      • ORM 的工作原理

        • ORM 框架通过映射关系(通常称为映射配置)将数据库表的字段与 Java 对象的属性进行绑定。ORM 框架执行 CRUD(创建、读取、更新、删除)操作时,框架会自动生成相应的 SQL 语句并与数据库交互,然后将数据库中的数据映射回 Java 对象。

          例如,一个 User 类的 Java 对象,可能会映射到数据库中的 users 表。User 类中的每个字段(例如 idnameemail)都与表中的相应列进行关联。

      • ORM 的常见框架

        • MyBatis (会写接入 )

        • Hibernate

        • JPA (Java Persistence API)

    • 2.2 集成 MyBatis 

      • 基于xml 配置的方式 前提是你连接池可以连接上你数据库
      • 2.2.1 引入pom.xml
        • ​​​​​​​
          mybatis主要配置
                 <dependency>
                      <groupId>org.mybatis</groupId>
                      <artifactId>mybatis</artifactId>
                      <version>3.5.10</version>
                  </dependency>
                  <dependency>
                      <groupId>org.mybatis</groupId>
                      <artifactId>mybatis-spring</artifactId>
                      <version>2.0.7</version>
                  </dependency>
          
          
               <!-- 分隔 -->
          
          
          <?xml version="1.0" encoding="UTF-8"?>
          <project xmlns="http://maven.apache.org/POM/4.0.0"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
              <modelVersion>4.0.0</modelVersion>
          
              <groupId>com.lirui</groupId>
              <artifactId>demo05</artifactId>
              <version>1.0-SNAPSHOT</version>
          
              <properties>
                  <maven.compiler.source>8</maven.compiler.source>
                  <maven.compiler.target>8</maven.compiler.target>
                  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
              </properties>
              <dependencies>
                  <!-- Spring Context -->
                  <dependency>
                      <groupId>org.springframework</groupId>
                      <artifactId>spring-context</artifactId>
                      <version>5.3.10</version>
                  </dependency>
          
                  <dependency>
                      <groupId>org.springframework</groupId>
                      <artifactId>spring-aop</artifactId>
                      <version>5.3.10</version>
                  </dependency>
          
                  <dependency>
                      <groupId>org.aspectj</groupId>
                      <artifactId>aspectjrt</artifactId>
                      <version>1.9.8</version>
                  </dependency>
          
                  <dependency>
                      <groupId>org.aspectj</groupId>
                      <artifactId>aspectjweaver</artifactId>
                      <version>1.9.8</version>
                  </dependency>
          
                  <dependency>
                      <groupId>org.apache.commons</groupId>
                      <artifactId>commons-dbcp2</artifactId>
                      <version>2.9.0</version>
                  </dependency>
          
                  <dependency>
                      <groupId>org.springframework</groupId>
                      <artifactId>spring-jdbc</artifactId>
                      <version>5.0.9.RELEASE</version>
                  </dependency>
          
                  <dependency>
                      <groupId>org.mybatis</groupId>
                      <artifactId>mybatis</artifactId>
                      <version>3.5.10</version>
                  </dependency>
                  <dependency>
                      <groupId>org.mybatis</groupId>
                      <artifactId>mybatis-spring</artifactId>
                      <version>2.0.7</version>
                  </dependency>
          
                  <!-- HikariCP 连接池依赖 -->
                  <dependency>
                      <groupId>com.zaxxer</groupId>
                      <artifactId>HikariCP</artifactId>
                      <version>3.4.5</version>
                  </dependency>
          
                  <dependency>
                      <groupId>mysql</groupId>
                      <artifactId>mysql-connector-java</artifactId>
                      <version>8.0.33</version>
                  </dependency>
          
                  <!-- Spring Beans -->
                  <dependency>
                      <groupId>org.springframework</groupId>
                      <artifactId>spring-beans</artifactId>
                      <version>5.3.10</version>
                  </dependency>
          
                  <dependency>
                      <groupId>org.springframework</groupId>
                      <artifactId>spring-context</artifactId>
                      <version>5.3.10</version>
                  </dependency>
              </dependencies>
          
          </project>
      • 2.2.2 编写配置文件​​​​​​​ applicationContext.xml
        • <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
                 xmlns:tx="http://www.springframework.org/schema/tx"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans
                                     http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
          
              <!--    applicationContext.xml 是 Spring 框架中的配置文件,
              通常用于定义 Spring IoC(控制反转)容器中的 Bean 配置和管理。
              这个文件主要用于将 Spring 的配置项和组件描述清楚,
              告知 Spring 容器如何实例化、配置和管理应用程序中的各种对象(Bean)。
              它是 Spring 配置的传统方式之一(除了注解和 Java 配置类)。-->
          
              <!-- HikariCP 配置 -->
              <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
                  <!-- 设置数据库连接池配置 -->
                  <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
                  <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/lirui?useSSL=false&amp;serverTimezone=UTC"/>
                  <property name="username" value="root"/>
                  <property name="password" value="root"/>
          
                  <!-- HikariCP 连接池相关参数 -->
                  <property name="maximumPoolSize" value="10"/> <!-- 最大连接数 -->
                  <property name="minimumIdle" value="5"/>     <!-- 最小空闲连接数 -->
                  <property name="connectionTimeout" value="30000"/> <!-- 连接超时(毫秒) -->
                  <property name="idleTimeout" value="600000"/> <!-- 空闲连接超时(毫秒) -->
                  <property name="maxLifetime" value="1800000"/> <!-- 连接最大生命周期(毫秒) -->
              </bean>
          
              <!-- SqlSessionFactory配置 -->
              <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
                  <!-- 将 HikariCP 数据源注入到 SqlSessionFactoryBean -->
                  <property name="dataSource" ref="dataSource"/>
                  <!-- 将 MyBatis 的 Mapper XML 文件路径注入到 SqlSessionFactoryBean -->
                  <property name="mapperLocations" value="classpath:mapper/*.xml"/>
              </bean>
          
              <!-- Mapper扫描  把你包下面的接口 注入-->
              <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
                  <property name="basePackage" value="com.lirui.demoMybatis"/>
              </bean>
          
              <!-- 提供事务管理 -->
              <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                  <property name="dataSource" ref="dataSource"/>
              </bean>
          
              <!-- 配置事务注解 -->
              <tx:annotation-driven transaction-manager="transactionManager"/>
          
          
              <!-- 配置 Engine Bean,带参数构造函数 -->
              <bean id="engine" class="com.lirui.car.Engine">
                  <constructor-arg value="V8"/>
              </bean>
          
              <!-- 配置 GPS Bean -->
              <bean id="gps" class="com.lirui.car.GPSImpl"/>
          
              <!-- 配置 Radio Bean -->
              <bean id="radio" class="com.lirui.car.RadioImpl"/>
          
              <!-- 配置 Car Bean,使用 setter 注入 -->
              <bean id="car" class="com.lirui.car.Car">
                  <property name="engine" ref="engine"/>
                  <property name="gps" ref="gps"/>
                  <property name="radio" ref="radio"/>
                  <property name="jdbcTemplate" ref="jdbcTemplate"/>
              </bean>
          
              <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                  <constructor-arg ref="dataSource"/>
              </bean>
          
          
          </beans>
          
      • 2.2.3 编写实体类
        • package com.lirui.demoMybatis.dao;
          
          public class User {
          
              private int id;
              private String name;
              private String email;
          
              // 默认构造方法
              public User() {}
          
              // 带参构造方法
              public User(int id, String name, String email) {
                  this.id = id;
                  this.name = name;
                  this.email = email;
              }
          
              // Getter 和 Setter 方法
              public int getId() {
                  return id;
              }
          
              public void setId(int 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;
              }
          
              // toString 方法
              @Override
              public String toString() {
                  return "User{" +
                          "id=" + id +
                          ", name='" + name + '\'' +
                          ", email='" + email + '\'' +
                          '}';
              }
          }
          
      • 2.2.4 编写mapper接口
        • package com.lirui.demoMybatis;
          
          import com.lirui.demoMybatis.dao.User;
          
          import java.util.List;
          
          public interface UserMapper {
          
              List<User> findAllUsers();
              User findUserById(int id);
              void insertUser(User user);
              void updateUser(User user);
              void deleteUser(int id);
          }
          
      • 2.2.5 编写mapper.xml
        • <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
          <mapper namespace="com.lirui.demoMybatis.UserMapper">
          
              <!-- 查询所有用户 -->
              <select id="findAllUsers" resultType="com.lirui.demoMybatis.dao.User">
                  SELECT id, name, email
                  FROM users
              </select>
          
              <!-- 根据 ID 查询用户 -->
              <select id="findUserById" parameterType="int" resultType="com.lirui.demoMybatis.dao.User">
                  SELECT id, name, email
                  FROM users
                  WHERE id = #{id}
              </select>
          
              <!-- 插入一个用户 -->
              <insert id="insertUser" parameterType="com.lirui.demoMybatis.dao.User">
                  INSERT INTO users (name, email)
                  VALUES (#{name}, #{email})
              </insert>
          
              <!-- 更新用户信息 -->
              <update id="updateUser" parameterType="com.lirui.demoMybatis.dao.User">
                  UPDATE users
                  SET name = #{name}, email = #{email}
                  WHERE id = #{id}
              </update>
          
              <!-- 删除用户 -->
              <delete id="deleteUser" parameterType="int">
                  DELETE FROM users WHERE id = #{id}
              </delete>
          
          </mapper>
          
      • 2.2.6 在使用的类 注入mapper类
        • 前提是在配置文件中 路径正确 能扫描到
        • package com.lirui.car;
          
          
          import com.lirui.demoMybatis.UserMapper;
          import com.lirui.demoMybatis.dao.User;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.jdbc.core.BeanPropertyRowMapper;
          import org.springframework.jdbc.core.JdbcTemplate;
          
          import javax.sql.DataSource;
          import java.sql.Connection;
          import java.sql.PreparedStatement;
          import java.sql.ResultSet;
          import java.sql.SQLException;
          import java.util.List;
          import java.util.Map;
          
          
          public class Car {
              private Engine engine;
              private GPS gps;
              private Radio radio;
              private JdbcTemplate jdbcTemplate;
          
              @Autowired
              private UserMapper userMapper;
          
          
              // Setters for dependency injection
              public void setEngine(Engine engine) {
                  this.engine = engine;
              }
          
              public void setGps(GPS gps) {
                  this.gps = gps;
              }
          
              public void setRadio(Radio radio) {
                  this.radio = radio;
              }
          
              public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
                  this.jdbcTemplate = jdbcTemplate;
              }
          
          
          
              public void drive() {
                  
                  List<User> allUsers = userMapper.findAllUsers();
                  for (User allUser : allUsers) {
                      System.out.println(allUser.getEmail());
                  }
                  System.out.println("引擎"+engine.getType() );
                  gps.navigate();
                  radio.playMusic();
              }
          }
          
      • 2.2.7 主函数调用
  • 3. 事务管理

    • 3.1 事务管理的基础概念

      • ​​​​​​​​​​​​​​事务是数据库管理系统中的一组操作,这些操作要么完全成功,要么完全失败。事务的基本特性(ACID)包括:

        • 原子性 (Atomicity):事务中的所有操作要么全部完成,要么全部不做。

        • 一致性 (Consistency):事务的执行必须将数据库从一种一致性状态转移到另一种一致性状态。

        • 隔离性 (Isolation):并发执行的事务之间应该相互隔离,事务的执行不应该受到其他事务的影响。

        • 持久性 (Durability):事务一旦提交,它对数据库的修改应该是永久性的。

      • 在 Spring 中,事务管理分为两种方式:

        • 声明式事务管理(使用 @Transactional 注解)

        • 编程式事务管理(通过 TransactionTemplateTransactionManager

    • 3.2 声明式事务管理(@Transactional)

      • ​​​​​​​​​​​​​​声明式事务管理是通过 AOP(面向切面编程)来管理事务。Spring 提供了 @Transactional 注解来简化事务管理。通过这种方式,不需要手动管理事务的开始、提交、回滚等,而是由 Spring 容器自动处理。
      • 使用 @Transactional 注解
        • 基础配置
          • 确保你的 Spring 配置文件中启用了事务管理。你可以在 applicationContext.xml 中添加如下配置:
          • <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                <property name="dataSource" ref="dataSource"/>
            </bean>
            
            <tx:annotation-driven transaction-manager="transactionManager"/>
            
          • tx:annotation-driven 告诉 Spring 容器启用基于注解的事务管理。
        • 在方法中使用 @Transactional
          • 在需要事务管理的方法上使用 @Transactional 注解,Spring 会自动处理该方法的事务。
          • ​​​​​​​​​​​​​​
            import org.springframework.stereotype.Service;
            import org.springframework.transaction.annotation.Transactional;
            
            @Service
            public class UserService {
            
                @Transactional
                public void createUser(User user) {
                    // 开始事务
                    userDao.save(user); // 执行数据库操作
                    // 如果发生异常,会自动回滚事务
                }
            }
            
        • 事务传播行为
          • @Transactional 注解有多个属性可以配置事务的行为,最常用的属性包括:

            • propagation:事务传播行为,表示当前事务如何与已有事务交互。常见值有:

              • REQUIRED(默认值):如果当前方法存在事务,则加入该事务,否则创建一个新事务。

              • REQUIRES_NEW:无论当前是否存在事务,都会新开一个事务。

              • SUPPORTS:如果当前方法存在事务,则使用该事务,否则以非事务方式执行。

            • isolation:事务隔离级别,表示事务对其他事务的可见性。常见值有:

              • READ_COMMITTED:读取已提交的数据。

              • READ_UNCOMMITTED:读取未提交的数据。

              • REPEATABLE_READ:确保事务在执行过程中读取到的数据始终一致。

              • SERIALIZABLE:最高的隔离级别,事务间完全隔离。

            • timeout:事务的超时时间,超过指定时间,事务会自动回滚。

            • rollbackFor:指定哪些异常会触发事务回滚。

            • @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
              public void someMethod() {
                  // 事务逻辑
              }
              
        • 回滚设置
          • 默认情况下,Spring 只会在遇到运行时异常(RuntimeException)时回滚事务。如果你希望指定的异常也回滚事务,可以通过 rollbackFornoRollbackFor 属性来指定:
          • @Transactional(rollbackFor = {SQLException.class, IOException.class})
            public void someMethod() {
                // 如果发生 SQLException 或 IOException,将会回滚事务
            }
            
    • 3.3 编程式事务管理

      • ​​​​​​​编程式事务管理是指在代码中手动控制事务的开始、提交和回滚。Spring 提供了 TransactionTemplatePlatformTransactionManager 来实现编程式事务管理。
      •  使用 TransactionTemplate
        • TransactionTemplate 是一种简化编程式事务管理的方式,利用它可以不需要显式地控制事务的提交和回滚。
        • import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Service;
          import org.springframework.transaction.PlatformTransactionManager;
          import org.springframework.transaction.TransactionStatus;
          import org.springframework.transaction.support.TransactionCallback;
          import org.springframework.transaction.support.TransactionTemplate;
          
          @Service
          public class UserService {
          
              @Autowired
              private PlatformTransactionManager transactionManager;
          
              @Autowired
              private UserDao userDao;
          
              public void createUser(User user) {
                  TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
                  transactionTemplate.execute(new TransactionCallback<Void>() {
                      @Override
                      public Void doInTransaction(TransactionStatus status) {
                          try {
                              userDao.save(user); // 执行数据库操作
                          } catch (Exception e) {
                              status.setRollbackOnly(); // 异常时标记事务回滚
                              throw e;
                          }
                          return null;
                      }
                  });
              }
          }
          
      • 使用 PlatformTransactionManagerTransactionStatus

        • ​​​​​​​如果希望有更多的控制权,也可以直接使用 PlatformTransactionManager 来手动管理事务。

        • import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Service;
          import org.springframework.transaction.PlatformTransactionManager;
          import org.springframework.transaction.TransactionStatus;
          import org.springframework.transaction.support.DefaultTransactionDefinition;
          
          @Service
          public class UserService {
          
              @Autowired
              private PlatformTransactionManager transactionManager;
          
              @Autowired
              private UserDao userDao;
          
              public void createUser(User user) {
                  // 创建事务定义
                  DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                  def.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_READ_COMMITTED);
                  def.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
          
                  // 开始事务
                  TransactionStatus status = transactionManager.getTransaction(def);
                  try {
                      userDao.save(user); // 执行数据库操作
                      transactionManager.commit(status); // 提交事务
                  } catch (Exception e) {
                      transactionManager.rollback(status); // 回滚事务
                      throw e;
                  }
              }
          }
          

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

初学者指南:用例图——开启您的软件工程之旅

目录 背景&#xff1a; 基本组成&#xff1a; 关联&#xff08;Assciation&#xff09;&#xff1a; 包含&#xff08;Include&#xff09;&#xff1a; 扩展&#xff08;Extend&#xff09;&#xff1a; 泛化&#xff08;Inheritance&#xff09;&#xff1a; 完整银行…

基于单片机洗衣机控制器的设计(论文+源码)

1需求分析 在智能洗衣机系统设计中&#xff0c;考虑到洗衣机在实际应用过程中&#xff0c;需要满足用户对于不同衣物清洁、消毒的应用要求&#xff0c;对设计功能进行分析&#xff0c;具体如下&#xff1a; 通过按键实现洗衣机不同工作模式的切换&#xff0c;包括标准模式&am…

qt QFontDialog详解

1、概述 QFontDialog 是 Qt 框架中的一个对话框类&#xff0c;用于选择字体。它提供了一个可视化的界面&#xff0c;允许用户选择所需的字体以及相关的属性&#xff0c;如字体样式、大小、粗细等。用户可以通过对话框中的选项进行选择&#xff0c;并实时预览所选字体的效果。Q…

Python学习从0到1 day27 第三阶段 Spark ③ 数据计算 Ⅱ

目录 一、Filter方法 功能 语法 代码 总结 filter算子 二、distinct方法 功能 语法 代码 总结 distinct算子 三、SortBy方法 功能 语法 代码 总结 sortBy算子 四、数据计算练习 需求&#xff1a; 解答 总结 去重函数&#xff1a; 过滤函数&#xff1a; 转换函数&#xff1a; 排…

今天,智谱「新清影」上线,率先进入有声视频生成时代!还要继续开源宠粉

来&#xff0c;你先把手机音量打开&#xff0c;然后去“听”下面一段视频&#xff1a; 你是不是一脸懵逼&#xff1f;不知道我想表达什么&#xff1f; 视频是AI生成的并不奇怪&#xff0c;但你可能没法相信&#xff0c;这个视频的音效&#xff0c;也是AI生成的。 火车鸣笛 你…

「Mac畅玩鸿蒙与硬件31」UI互动应用篇8 - 自定义评分星级组件

本篇将带你实现一个自定义评分星级组件&#xff0c;用户可以通过点击星星进行评分&#xff0c;并实时显示评分结果。为了让界面更具吸引力&#xff0c;我们还将添加一只小猫图片作为评分的背景装饰。 关键词 UI互动应用评分系统自定义星级组件状态管理用户交互 一、功能说明 …

pdf转excel;pdf中表格提取

一、问题描述 在工作中或多或少会遇到&#xff1a;需要将某份pdf中的表格数据提取出来&#xff0c;以便能够“修改使用”数据 可将pdf中的表格提取出来&#xff0c;解决办法还有点复杂 尤其涉及“pdf中表格不是标准的单元格”的时候&#xff0c;提取数据到excel不太容易 比…

IT架构管理

目录 总则 IT架构管理目的 明确组织与职责 IT架构管理旨在桥接技术实施与业务需求之间的鸿沟&#xff0c;通过深入理解业务战略和技术能力&#xff0c;推动技术创新以支持业务增长&#xff0c;实现技术投资的最大价值。 设定目标与范围 IT架构管理的首要目的是确立清晰的组织…

小红书图文矩阵的运营策略与引流技巧解析

内容概要 小红书图文矩阵是一种高效的内容运营方式&#xff0c;能够帮助品牌在竞争激烈的环境中脱颖而出。通过构建矩阵账号&#xff0c;品牌可以实现多维度的内容覆盖&#xff0c;创造出丰富而立体的用户体验。为什么要做图文矩阵&#xff1f;首先&#xff0c;这种方式能够提…

python中常见的8种数据结构之一元组

元组&#xff08;tuple&#xff09;是Python中常见的数据结构之一&#xff0c;它是一个有序、不可变的序列。元组使用圆括号来表示&#xff0c;可以包含任意类型的元素&#xff0c;包括数字、字符串、列表等。元组的元素可以通过索引访问&#xff0c;但是不能修改。 下面是一些…

计算机毕业设计Python+大模型动漫推荐系统 动漫视频推荐系统 机器学习 协同过滤推荐算法 bilibili动漫爬虫 数据可视化 数据分析 大数据毕业设计

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…

【leetcode练习·二叉树】用「分解问题」思维解题 I

本文参考labuladong算法笔记[【强化练习】用「分解问题」思维解题 I | labuladong 的算法笔记] 105. 从前序与中序遍历序列构造二叉树 | 力扣 | LeetCode | 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵…

产品经理晋级-Axure中继器制作美观表格

这里的效果&#xff0c;步骤如下&#xff1a; 点击中继器&#xff0c;输入表格信息&#xff1b;在中继器中创建表格内容&#xff0c;把你想要的效果制作在中继器中&#xff0c;表头有几个表格&#xff0c;这边就对应多少个。 按照视频的过程把中继器双击后-样式中的文本内容&am…

防火墙|WAF|漏洞|网络安全

防火墙|WAF|漏洞|网络安全 防火墙 根据内容分析数据包&#xff1a; 1、源IP和目的IP地址 2、有效负载中的内容。 3、数据包协议&#xff08;例如&#xff0c;连接是否使用 TCP/IP 协议&#xff09;。 4、应用协议&#xff08;HTTP、Telnet、FTP、DNS、SSH 等&#xff09;。 5…

【Linux系统编程】第四十四弹---从TID到线程封装:全面掌握线程管理的核心技巧

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、tid是什么 1.1、理解库 1.2、理解tid 1.3、tid中线程局部存储 2、封装线程 2.1、基本结构 2.2、函数实现 2.3、使用…

医学图像算法之基于Unet的视网膜血管分割

第一步&#xff1a;准备数据 视网膜血管分割数据比较少&#xff0c;但效果好&#xff0c;总共40张 第二步&#xff1a;搭建模型 UNet主要贡献是在U型结构上&#xff0c;该结构可以使它使用更少的训练图片的同时&#xff0c;且分割的准确度也不会差&#xff0c;UNet的网络结构…

ARM死机(HardFault)调试技巧详解(栈回溯,不破坏现场)

目录 Keil调试技巧&#xff1a; 一.不破坏现场连接仿真器与进入debug 二.栈回溯 死机调试示例 J-Link调试方法 示例&#xff1a;空指针异常 不能连接烧录器或者读取内存怎么办&#xff1f; 在日常开发中&#xff0c;经常会遇到单片机卡死机等问题&#xff0c;经常很难定…

nodejs 020: React语法规则 props和state

props和state 在 React 中&#xff0c;props 和 state 是管理数据流的两种核心机制。理解它们之间的区别和用途是构建 React 应用程序的基础。 一、props 和 state的区别 特性propsstate定义方式由父组件传递给子组件的数据组件内部管理的本地数据是否可修改不可变&#xff…

【开源免费】基于SpringBoot+Vue.JS水果购物网站(JAVA毕业设计)

博主说明&#xff1a;本文项目编号 T 065 &#xff0c;文末自助获取源码 \color{red}{T065&#xff0c;文末自助获取源码} T065&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

python可视化进阶

引用&#xff1a; 首先需要安装 plotnine from plotnine import* import joypy数据可视化进阶操作 3.1 类别数据可视化 【例3-1】——绘制简单条形图 【代码框3-1】——绘制简单条形图 # 图3-1的绘制代码 import pandas as pd import matplotlib.pyplot as plt from cvxpy …