spring事务的一些知识点
所属分类 spring
浏览量 21
org.springframework.jdbc.datasource.DataSourceUtils
org.springframework.transaction.support.TransactionSynchronizationManager
1. 获取 DataSource
DataSource 是 Spring 管理的数据库连接池对象,通常通过依赖注入或上下文获取
方式1:通过 @Autowired 注入
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.sql.DataSource;
@Service
public class MyService {
@Autowired
private DataSource dataSource;
public void doSomething() {
// 使用 dataSource 获取连接
}
}
方式2:通过 ApplicationContext 获取
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.sql.DataSource;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = context.getBean(DataSource.class);
}
}
2. 获取 JDBC 连接
在 Spring 中,不建议直接使用 DataSource.getConnection(),因为这会绕过 Spring 的事务管理;
推荐通过以下方式获取连接:
方式1:使用 DataSourceUtils(推荐)
DataSourceUtils 是 Spring 提供的工具类,确保连接与当前事务绑定。
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.sql.DataSource;
import java.sql.Connection;
public class MyService {
private final DataSource dataSource;
public MyService(DataSource dataSource) {
this.dataSource = dataSource;
}
public void doSomething() {
Connection connection = DataSourceUtils.getConnection(dataSource);
try {
// 使用 connection 执行操作
} finally {
DataSourceUtils.releaseConnection(connection, dataSource); // 自动回滚或提交事务
}
}
}
方式2:使用 TransactionSynchronizationManager(高级)
如果需要手动绑定连接到当前事务,可以通过 TransactionSynchronizationManager 获取:
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.sql.DataSource;
import java.sql.Connection;
public class MyService {
private final DataSource dataSource;
public MyService(DataSource dataSource) {
this.dataSource = dataSource;
}
public void doSomething() {
Connection connection = null;
try {
// 如果当前存在事务,返回绑定到事务的连接;否则返回新连接
connection = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource().getConnection();
// 使用 connection
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close(); // 手动关闭连接
}
}
}
}
TransactionAwareDataSourceProxy 是 Spring 对 DataSource 的代理,确保连接与事务绑定;
需要确保 DataSource 是通过 Spring 配置的代理对象
3. 在事务中获取连接
在 Spring 事务方法中,直接使用 JdbcTemplate 或 NamedParameterJdbcTemplate 是推荐的方式,因为它们会自动管理连接和事务
示例:使用 JdbcTemplate
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Transactional
public void doSomething() {
jdbcTemplate.update("INSERT INTO users (name) VALUES (?)", "Alice");
}
}
4. 手动管理连接(不推荐)
如果必须手动管理连接(例如执行原生 SQL),请确保连接与事务绑定,并在 finally 块中释放资源:
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class MyService {
private final DataSource dataSource;
public MyService(DataSource dataSource) {
this.dataSource = dataSource;
}
@Transactional
public void doSomething() {
Connection connection = null;
PreparedStatement ps = null;
try {
connection = DataSourceUtils.getConnection(dataSource);
ps = connection.prepareStatement("INSERT INTO users (name) VALUES (?)");
ps.setString(1, "Bob");
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (ps != null) ps.close();
DataSourceUtils.releaseConnection(connection, dataSource); // 自动提交或回滚
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
5. 关键点总结
场景 推荐方式
使用事务管理 JdbcTemplate 或 ORM 框架(如 MyBatis),Spring 自动管理连接和事务
手动获取连接(绑定事务) 使用 DataSourceUtils.getConnection(dataSource) 和 releaseConnection()
需要直接操作 Connection 确保通过 Spring 代理的 DataSource 获取连接,并绑定到当前事务
避免资源泄漏 在 finally 块中调用 releaseConnection() 或 close()
6. 常见问题
Q1: 为什么直接调用 DataSource.getConnection() 会出问题?
事务隔离:直接获取的连接不会参与 Spring 的事务管理,可能导致事务不一致
连接复用:Spring 事务中可能已经绑定了连接,直接获取会创建新连接,破坏事务上下文
Q2: 如何确保手动操作的连接与事务绑定?
使用 DataSourceUtils.getConnection(dataSource),Spring 会自动绑定到当前事务
使用 TransactionAwareDataSourceProxy 代理 DataSource
Q3: 是否需要显式关闭连接?
使用 DataSourceUtils.releaseConnection():会根据事务状态自动提交或回滚,并释放连接
直接调用 connection.close():可能破坏事务,仅在非事务场景下使用
7. 配置示例(Spring Boot)
在 Spring Boot 中,DataSource 通常由框架自动配置,只需注入即可:
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
通过以上方式,可以安全地在 Spring 中获取 DataSource 和 JDBC 连接,并确保与事务管理无缝集成
上一篇
下一篇
CPI PPI PMI
springboot自定义日志注解
词向量 Word Embedding
MyBatis Plus 动态数据源注解 @DS 注解
MyBatis Plus @DS注解原理
多个AOP切面注解 执行顺序说明