博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JdbcUtils针对事务问题作出的第三次修改
阅读量:6464 次
发布时间:2019-06-23

本文共 9524 字,大约阅读时间需要 31 分钟。

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
t1=new ThreadLocal
(); /** * 使用连接池返回一个连接对象 * @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 query(String sql, Object param, ResultSetHandler
rsh) throws SQLException { Connection con=JdbcUtils.getConnection(); T result=super.query(con, sql, param,rsh); JdbcUtils.releaseConnection(con); return result; } @Override public
T query(String sql, Object[] params, ResultSetHandler
rsh) throws SQLException { Connection con=JdbcUtils.getConnection(); T result=super.query(con,sql, params, rsh); JdbcUtils.releaseConnection(con); return result; } @Override public
T query(String sql, ResultSetHandler
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 query(String sql, ResultSetHandler
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;    }    }}

 

转载地址:http://nghzo.baihongyu.com/

你可能感兴趣的文章
梯度下降(Gradient descent)
查看>>
Windows平台分布式架构实践 - 负载均衡
查看>>
如何让LinearLayout也有类似Button的点击效果?
查看>>
JAVA读取文件方法大全
查看>>
寻找最小的k个数
查看>>
CSS3中的动画效果记录
查看>>
CI框架整合微信公共平台接口
查看>>
request.getScheme()的使用方法
查看>>
Android快速开发常用知识点系列目录
查看>>
Java ActiveMQ队列模式案例
查看>>
EJB2的配置
查看>>
最容易理解的对卷积(convolution)的解释
查看>>
《机器学习实战》知识点笔记目录
查看>>
Linux操作系统实时性分析
查看>>
完美解决NC502手工sql的查询引擎排序及合计问题
查看>>
Tiny语言执行环境TM机源码
查看>>
PE文件之资源讲解
查看>>
windows 7/mac编译cocos2d-x-3.2*的android工程报错
查看>>
MYSQL导入导出.sql文件(转)
查看>>
git review报错一例
查看>>