ThreadLocal封装Connection--事务统一管理
ThreadLocal:线程本地变量该类提供了线程局部变量。这些变量不同于它们的普通对应物,因为访问一个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的私有静态字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
事务是一种机制、是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行。因此事务是一个不可分割的工作逻辑单元。在数据库系统上执行并发操作时事务是作为最小的控制单元来使用的。这特别适用于多用户同时操作的数据通信系统。
在业务逻辑中我们要统一管理事务,但是在一个事务中会涉及到多个Dao,不同的DAO取得的是不同的Connection对象,这样就不能实现统一管理事务。
那么怎么才能实现两个或多个DAO用同一个事务来控制,来统一管理事务那?
首先就要解决一个根本问题,我们在一个事务中,不同的DAO取得的是同一个Connection,这个要怎么实现呢。我们想到了TheadLocal.
因为当一个业务逻辑要对多个DAO进行处理的时候,此操作属于同一个线程内。所以,我们希望能把此Connection放在线程内,或者和线程有关联。
在任何一个线程内都可以用ThreadLocal来保存一个变量的copy,这样,如果此对象存在,就可以直接取用。
如果ThreadLocal中放置connection, 保证事务中的DAO类获取的都是同一个connection,这样才保证事务。所以,在同一个线程内,不同的DAO就可以保证取得到的是同一个Connection
这样就实现了,事务的统一管理
ThreadLocal的API如下图:
下面是ThreadLocal对Connection的封装
/*
*采用ThreadLocal封装Connection
*
*/
public Class ConnectionManager {
//创建一个私有静态的并且是与事务相关联的局部线程变量
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>;
public static Connection getConnection(){
//获得线程变量connectionHolder的值conn
Connection conn = connectionHolder.get();
if (conn == null){
//如果连接为空,则创建连接,另一个工具类,创建连接
conn = DbUtil.getConnection();
//将局部变量connectionHolder的值设置为conn
connectionHolder.set(conn);
}
return conn;
}
/**
* 关闭连接和从线程变量中删除conn
*/
public static void closeConnection(){
//获得线程变量connectionHolder的值conn
Connection conn = connectionHolder.get();
if (conn != null){
try {
//关闭连接
conn.close();
//从线程局部变量中移除conn,如果没有移除掉,下次还会用这个已经关闭的连接,就会出错
connectionHolder.remove();
}catch(SQLException e){
e.printStackTrace();
}
}
}
/**
*开启事务,手动开启
*/
public static void beginTransaction(Connection conn){
try {
//如果连接存在,再设置连接,否则会出错
if (conn != null){
//默认conn是自动提交,
if (conn.getAutoCommit()){
//关闭自动提交,即是手动开启事务
conn.setAutoCommit(false);
}
}
}catch(SQLException e){
e.printStackPrince();
}
}
/**
* 提交事务
*/
public static void commitTransaction(Connection conn){
try{
if (conn != null){
if (!conn.getAutoCommit()){
conn.commit();
}
}
}catch(SQLException e){
e.printStackTrace();
}
}
/**
* 回滚事务
*/
public static void rollbackTransaction(){
try {
if (conn != null){
if(!conn.getAutoCommit()){
conn.rollback();
}
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
//调用业务逻辑事务管理
public void addFlowCard(FlowCard flowCard)
Connection conn = null;
try {
//从ThreadLocal中取得Connection
conn = ConnectionManager.getConnection();
//手动控制事务提交
ConnectionManager.beginTransaction(conn);
//添加流向单主信息
flowCardDao.addFlowCardMaster(flowCardVouNo, flowCard);
//添加流向单明细信息
flowCardDao.addFlowCardDetail(flowCardVouNo, flowCard.getFlowCardDetailList());
if (!conn.getAutoCommit()) {
//提交事务
ConnectionManager.commitTransaction(conn);
}
}catch(Exception e) {
e.printStackTrace();
if (!conn.getAutoCommit()) {
//回滚事务
ConnectionManager.rollbackTransaction(conn);
}
throw new ApplicationException("操作失败!");
}finally {
ConnectionManager.closeConnection();
}
}
分享到:
相关推荐
总的来说,结合JDBC的事务管理和ThreadLocal,我们可以在多线程环境中更好地实现数据库操作,确保数据的一致性,并提高代码的可复用性和安全性。通过使用ThreadLocal,我们可以创建线程安全的变量,使得每个线程都能...
在事务管理中,我们可以在ThreadLocal中存储当前线程的`Connection`对象,这样每个线程都有自己的事务上下文,避免了并发问题。 在文件`Transaction3`中,可能包含了具体实现上述模板设计模式的Java代码,包括`...
4. 事务管理:在需要开启事务的场景,可以在ThreadLocal中设置一个标识,表示当前线程正在处理事务。这样,所有的数据库操作都会在这个事务范围内进行,直到提交或回滚事务。 5. 返还连接:操作完成后,将连接返回给...
为了保证事务的一致性,可以利用`ThreadLocal`来封装`Connection`,确保在同一事务中的DAO类获取的是同一个`Connection`。 #### JTA事务 JTA(Java Transaction API)用于管理分布式事务。一个完整的JTA事务包括一...
在事务开始时,Spring会创建一个Session并将其绑定到当前线程,这个绑定过程使用了ThreadLocal变量,保证了在同一个线程中的事务操作可以访问到相同的Session,也就确保了Connection的一致性。 此外,Spring还提供...
在Java编程中,连接数据库是常见的任务,尤其是在开发基于服务器的应用程序时。...这个简单的`DBUtil`类展示了如何使用JDBC与MySQL进行交互,但实际应用中,你可能还需要考虑更多高级功能,如事务管理、连接池等。
ThreadLocal使用案例_动力节点Java学院整理 ThreadLocal是Java中的一种多线程机制,主要用于解决多线程之间的共享变量问题。在Java中,每个线程都有自己的ThreadLocal变量副本,通过ThreadLocal可以实现线程安全的...
Java面试的第23天,我们来探讨几个关键的Java技术点:JDBC事务控制、批处理、ThreadLocal的工作原理、分页查询及其优化,以及DAO层事务的封装。 1. JDBC事务控制: JDBC提供了对数据库事务的管理,主要通过`...
SessionFactory的管理至关重要,因为Session的生命周期管理和JDBC中的Connection管理类似。通过ThreadLocal对象,如`localSession`,可以在多线程环境下为每个线程维护独立的Session实例,避免了频繁创建和销毁...