目录
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(); }
-
- pom.xml
-
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&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(); } }
-
- pom.xml (1.8版本 选3.x 11及以上 5.x)
-
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&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()); } }
- 在使用 JdbcTemplate 进行数据库操作时,Spring 的事务管理框架可以确保一组数据库操作要么全部成功,要么全部回滚。Spring 支持声明式事务管理,可以通过
- 增、删、改操作
- 配置类
-
-
1.3 总结:
-
MySQL:关系型数据库,提供 JDBC 驱动程序让 Java 应用程序可以与它连接。
-
JDBC 驱动:MySQL 提供
com.mysql.cj.jdbc.Driver
驱动,让 Java 可以通过 JDBC 与 MySQL 进行交互。 -
数据库连接池:
-
DBCP2 和 HikariCP 都是连接池实现,负责管理数据库连接。
-
连接池的目的是提高性能,避免每次数据库操作都创建和销毁连接。
-
-
优化:
-
HikariCP:提供更高性能的连接池,减少连接获取和释放的延迟,是当前推荐的连接池。
-
DBCP2:是另一个常用的连接池,性能稍逊于 HikariCP,但依然可靠。
-
-
Spring JDBC:
-
提供简化的数据库操作,利用
JdbcTemplate
简化查询、插入等操作。 -
与 DBCP2 或 HikariCP 配合使用,通过
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
类中的每个字段(例如id
、name
、email
)都与表中的相应列进行关联。
-
-
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&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
注解) -
编程式事务管理(通过
TransactionTemplate
或TransactionManager
)
-
-
-
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 容器启用基于注解的事务管理。
- 确保你的 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
)时回滚事务。如果你希望指定的异常也回滚事务,可以通过rollbackFor
或noRollbackFor
属性来指定: -
@Transactional(rollbackFor = {SQLException.class, IOException.class}) public void someMethod() { // 如果发生 SQLException 或 IOException,将会回滚事务 }
- 默认情况下,Spring 只会在遇到运行时异常(
- 基础配置
- 声明式事务管理是通过 AOP(面向切面编程)来管理事务。Spring 提供了
-
3.3 编程式事务管理
- 编程式事务管理是指在代码中手动控制事务的开始、提交和回滚。Spring 提供了
TransactionTemplate
和PlatformTransactionManager
来实现编程式事务管理。 - 使用
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; } }); } }
-
使用
PlatformTransactionManager
和TransactionStatus
-
如果希望有更多的控制权,也可以直接使用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; } } }
-
- 编程式事务管理是指在代码中手动控制事务的开始、提交和回滚。Spring 提供了
-