JdbcUtils针对事务问题作出的第三次修改
DAO中的事务
其实在DAO中处理事务真的是“小菜一碟”
try{
con.commit();
}catch(Exception e){
con.rollback();
}
但是dao层中只能是对账户金额的修改而不是业务的处理
service层中也可以使用刚才的格式,使用con会暴露出service直接使用数据库的问题
我们希望这样来处理事务:
public class XXXService(){
private XXXDao dao=new XXXDao();
public void serviceMethod(){
try{
JdbcUtils.beginTransaction();
dao.daoMethod1(...);
dao.daoMethod2(...);
JdbcUtils.commitTransaction();
}catch(Exception e){
JdbcUtils.rollbackTransaction();
}
}
}
修改后:
package cn.itcast.cn; import java.sql.Connection;
import java.sql.SQLException; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class JdbcUtils {
/*
* 配置文件的恶魔人配置!要求你必须给出c3p0-config。xnl!
*/
private static ComboPooledDataSource dataSource=new ComboPooledDataSource("oracle-config");
/**
* 它是事务专用连接
*/
private static Connection con=null;
/**
* 使用连接池返回一个连接对象
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
//当con!=null,表示已经调用过beginTransaction方法了
if(con!=null) return con;
return dataSource.getConnection();
} /**
* 返回连接池对象
* @return
*/
public static DataSource getDataSource(){
return dataSource;
}
/**
* 1、开启一个Connection,设置它的setAutoCommit(false)
* 2、还要保证dao中使用的连接是我们刚刚创建的
* ------------------------
* 1、创建一个Connection,设置为手动提交
* 2、把这个Connection给dao用
* 3、还要让commitTransaction或rollbackTransaction可以获取到
* @throws SQLException
*/
public static void beignTransaction() throws SQLException{
if(con!=null) throw new SQLException("已经开始了事务,就不要继续开启事务了!");
con=getConnection();
con.setAutoCommit(false);
}
/**
* 提交事务
* 获取之前开启的Connection,兵提交
* @throws SQLException
*/
public static void commitTransaction() throws SQLException{
if(con==null) throw new SQLException("还没有开启事务,不能提交!");
con.commit();
con.close();
con=null;//因为前面的close()不会销毁连接而是放回连接池
}
/**
* 回滚事务
* 获取之前开启的Connection,兵回滚
* @throws SQLException
*/
public static void rollbackTransaction() throws SQLException{
if(con==null) throw new SQLException("还没有开启事务,不能提交!");
con.rollback();
con.close();
con=null;//因为前面的close()不会销毁连接而是放回连接池
}
}
package cn.itcast.cn; import java.sql.Connection;
import java.sql.SQLException; import org.apache.commons.dbutils.QueryRunner; public class AccountDao {
public static void update(String name,double money) throws SQLException{
QueryRunner qr=new QueryRunner();
String sql="UPDATE account SET balance=balance+? WHERE aname=?";
Object[] params={money,name}; //我们需要自己来提供连接,保证多次调用使用的是同一个连接
Connection con=JdbcUtils.getConnection();
qr.update(con, sql, params);
}
}
package cn.itcast.cn;
import java.sql.SQLException;
import org.junit.Test;
@SuppressWarnings("static-access")
public class Demo1 {
private AccountDao dao=new AccountDao();
@Test
public void serviceMethod(){
try{
JdbcUtils.beignTransaction();
dao.update("zs", -1000);
dao.update("lisi", +1000);
JdbcUtils.commitTransaction();
}catch(Exception e){
try {
JdbcUtils.rollbackTransaction();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
}
针对前面的针对多线程并发问题和代码复杂度问题作出的再次优化:
package cn.itcast.cn; import java.sql.Connection;
import java.sql.SQLException; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class JdbcUtils {
/*
* 配置文件的恶魔人配置!要求你必须给出c3p0-config。xnl!
*/
private static ComboPooledDataSource dataSource=new ComboPooledDataSource();
/**
* 它是事务专用连接
*/
private static ThreadLocal<Connection> t1=new ThreadLocal<Connection>();
/**
* 使用连接池返回一个连接对象
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
//当con!=null,表示已经调用过beginTransaction方法了
Connection con=t1.get();
if(con!=null) return con;
return dataSource.getConnection();
} /**
* 返回连接池对象
* @return
*/
public static DataSource getDataSource(){
return dataSource;
}
/**
* 1、开启一个Connection,设置它的setAutoCommit(false)
* 2、还要保证dao中使用的连接是我们刚刚创建的
* ------------------------
* 1、创建一个Connection,设置为手动提交
* 2、把这个Connection给dao用
* 3、还要让commitTransaction或rollbackTransaction可以获取到
* @throws SQLException
*/
public static void beignTransaction() throws SQLException{
Connection con=t1.get();
if(con!=null) throw new SQLException("已经开始了事务,就不要继续开启事务了!");
con=getConnection();
con.setAutoCommit(false);
t1.set(con);//把连接保存起来
}
/**
* 提交事务
* 获取之前开启的Connection,兵提交
* @throws SQLException
*/
public static void commitTransaction() throws SQLException{
Connection con=t1.get();
if(con==null) throw new SQLException("还没有开启事务,不能提交!");
con.commit();
con.close();
// con=null;//因为前面的close()不会销毁连接而是放回连接池
t1.remove();//从t1中移除连接
}
/**
* 回滚事务
* 获取之前开启的Connection,兵回滚
* @throws SQLException
*/
public static void rollbackTransaction() throws SQLException{
Connection con=t1.get();
if(con==null) throw new SQLException("还没有开启事务,不能提交!");
con.rollback();
con.close();
// con=null;//因为前面的close()不会销毁连接而是放回连接池
t1.remove();
} public static void releaseConnection(Connection connection) throws SQLException{
/*
*判斷它是不是中事務專用,如果是就不關閉
*如果不是就要關閉
*/
//如果con==null,說明沒有事務,那麼connection一定不是事務專用的
Connection con=t1.get();
if(con==null) connection.close();
if(con!=connection) connection.close(); }
}
package cn.itcast.cn; import java.sql.Connection;
import java.sql.SQLException; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
/**
* 这个类中的方法自己来处理连接的问题
* 无需外界传递
* 怎么处理的呢?
* 通过JdbcUtils.getConnection()得到连接!有可能是事务连接也有可能是普通连接
* JdbcUtils.releaseConnection()完成连接的释放
* @author Administrator
*
*/
public class TxQueryRunner extends QueryRunner{ @Override
public int[] batch(String sql, Object[][] params) throws SQLException {
/**
* 得到连接
* 执行父类方法
* 释放连接
* 返回值
*/
Connection con=JdbcUtils.getConnection();
int[] result=super.batch(con, sql, params);
JdbcUtils.releaseConnection(con);
return result;
} @Override
public <T> T query(String sql, Object param, ResultSetHandler<T> rsh)
throws SQLException {
Connection con=JdbcUtils.getConnection();
T result=super.query(con, sql, param,rsh);
JdbcUtils.releaseConnection(con);
return result;
} @Override
public <T> T query(String sql, Object[] params, ResultSetHandler<T> rsh)
throws SQLException {
Connection con=JdbcUtils.getConnection();
T result=super.query(con,sql, params, rsh);
JdbcUtils.releaseConnection(con);
return result;
} @Override
public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
throws SQLException {
Connection con=JdbcUtils.getConnection();
T result=super.query(con,sql, rsh,params);
JdbcUtils.releaseConnection(con);
return result;
} @Override
public <T> T query(String sql, ResultSetHandler<T> rsh) throws SQLException {
Connection con=JdbcUtils.getConnection();
T result=super.query(con,sql, rsh);
JdbcUtils.releaseConnection(con);
return result;
} @Override
public int update(String sql) throws SQLException {
Connection con=JdbcUtils.getConnection();
int result=super.update(con,sql);
JdbcUtils.releaseConnection(con);
return result;
} @Override
public int update(String sql, Object param) throws SQLException {
Connection con=JdbcUtils.getConnection();
int result=super.update(con,sql,param);
JdbcUtils.releaseConnection(con);
return result;
} @Override
public int update(String sql, Object... params) throws SQLException {
Connection con=JdbcUtils.getConnection();
int result=super.update(con,sql,params);
JdbcUtils.releaseConnection(con);
return result;
} }
package cn.itcast.cn;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
public class AccountDao {
public static void update(String name,double money) throws SQLException{
// QueryRunner qr=new QueryRunner();
QueryRunner qr=new TxQueryRunner();
String sql="UPDATE account SET balance=balance+? WHERE aname=?";
Object[] params={money,name};
//我们需要自己来提供连接,保证多次调用使用的是同一个连接
// Connection con=JdbcUtils.getConnection();
// qr.update(con, sql, params);
// JdbcUtils.releaseConnection(con);
qr.update(sql,params);
}
}
package cn.itcast.cn;
import java.sql.SQLException;
import org.junit.Test;
@SuppressWarnings("static-access")
public class Demo1 {
private AccountDao dao=new AccountDao();
@Test
public void serviceMethod() throws Exception{
try{
JdbcUtils.beignTransaction();
dao.update("zs", -1000);
if(true) throw new RuntimeException("不好依稀");
dao.update("lisi", +1000);
JdbcUtils.commitTransaction();
}catch(Exception e){
try {
JdbcUtils.rollbackTransaction();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw e;
}
}
}
JdbcUtils针对事务问题作出的第三次修改的更多相关文章
- 【转】Pandas学习笔记(三)修改&添加值
Pandas学习笔记系列: Pandas学习笔记(一)基本介绍 Pandas学习笔记(二)选择数据 Pandas学习笔记(三)修改&添加值 Pandas学习笔记(四)处理丢失值 Pandas学 ...
- Mac OS 下三种修改Hosts文件的方法
一.系统偏好设置修改 1.打开系统偏好设置,底部有一个Hosts的快捷入口2.输入ip和hostname后,回车确定,勾选改host即可 二.终端命令行修改 sudo vi /etc/hosts ...
- 分布式事务专题笔记(三)分布式事务解决方案之TCC(三阶段提交)
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.什么是TCC事务 TCC是Try.Confifirm.Cancel三个词语的缩写,TCC要求每个分支 ...
- 【Spring】事务的执行原理(三)
事务的回滚 如果获取事务属性不为空,并且抛出的异常是RuntimeException或者Error类型,调用事务管理器中的rollback方法进行回滚 如果事务属性为空或者抛出的异常不是Runtime ...
- SQL Server提高事务复制效率优化(三)订阅初始化优化
初始化订阅主要是由分发代理分发和应用快照代理之前生成的快照,所以优化的主体是分发代理. 1.初始化订阅 首先在本地创建一个订阅,发布服务器.分发服务器和订阅服务器都在同一台服务器上,仅为了测试生产环境 ...
- uvm_tlm_if_base——TLM1事务级建模方法(三)
文件: src/tlm1/uvm_tlm_ifs.svh 类: uvm_tlm_if_base 这个类没有派生自任何类,在类的中,定义了三类接口:第一类是阻塞性质的普通方法(task),put, ge ...
- SqlServer 并发事务:死锁跟踪(三)6种跟踪死锁的方法总结 大神
http://blog.csdn.net/kk185800961/article/details/42504857
- 小丁带你走进git的世界三-撤销修改
一.撤销指令 git checkout还原工作区的功能 git reset 还原暂存区的功能 git clean 还没有被添加进暂存区的文件也就是git还没有跟踪的文件可以使用这个命令清除他们 g ...
- SQL Server提高事务复制效率优化(四)修改数据同步过程优化
1.原理 我说的数据修改同步过程指的是在快照生成完毕,分发代理将快照应用于订阅服务器完成订阅服务器初始化后,发布服务器后续的更改同步到订阅服务器过程,这也就是我们常常关注的延迟.此过程主要 ...
随机推荐
- 【SQLServer2008】之Win10 安装 SQL Server 2008
查看安装步骤链接: http://jingyan.baidu.com/article/1709ad8092be974634c4f0e7.html
- laravel学习之路2: jwt集成
"tymon/jwt-auth": "^1.0@dev", 执行 composer update 'providers' => [ .... Tymon\ ...
- 嵌入式开发之davinci--- 8148/8168/8127 中的大屏分布式拼接显示系统
其实在接触从12年接触8127系列ipnc 时看到200w和500w的高清像素,我就萌生了视频拼接的兴趣,没想到今年的安博会就有公司推出产品了,它就是上海的环视科技,从他的主页可以看到,明显的有个只能 ...
- linux 常用的17个性能指标
1.Average load:Average number of processes simultaneously in Ready state during the last minute. 上 ...
- SDOI2012 Round1 day2 集合(set)解题报告
//=====================以上为官方题解==============// 数据略水,暴力枚举50. 把边按照升序排一遍,在询问,水过. #include<cstdio> ...
- poj3292
Semi-prime H-numbers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8677 Accepted: 3 ...
- Gone Fishing(贪心)
Gone Fishing John is going on a fising trip. He has h hours available (1 ≤ h ≤ 16), and there are n ...
- [note]CRT&exCRT
中国剩余定理 别人的blog 假设现在有关于x的同余方程组(p1,p2均为质数) \(x=a_1\pmod {p_1}\) \(x=a_2\pmod {p_2}\) 可以转化成如下形式 \(x=a_1 ...
- vue 计算属性和监听器
一.计算属性 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护.例如: <div> {{ message.split('').rev ...
- Django 视图之CBV
CBV 所谓的CBV(class base view) 在视图里面,用类的方式来写逻辑 那么对于FBV,CBV有什么优势? CBV(class base views) 就是在视图里使用类处理请求. P ...