代码调用DruidDataSource来管理conn连接,同时声明了ThreadLocal对象来保存每次线程请求所获取的连接,这样可以避免每个new一个JDBC

本文介绍了一种使用Druid连接池结合ThreadLocal管理数据库连接的方法,通过将连接保存在线程局部变量中以减少频繁创建连接带来的性能损耗。

代码调用DruidDataSource来管理conn连接,同时声明了ThreadLocal对象来保存每次线程请求所获取的连接,这样可以避免每个new一个JDBCUtils对象,将conn对象放在ThreadLocal对象中缓存起来,下次调用直接从ThreadLocal中获取来实现性能的提高。

package com.util;
 
import java.sql.Connection;
import java.sql.SQLException;
 
import com.alibaba.druid.pool.DruidDataSource;
/**
 * JDBC封装类
 * @author DC
 *
 */
public class JDBCUtils{
    private static DruidDataSource dataSource  = new DruidDataSource();
    //声明线程共享变量
    public static ThreadLocal<Connection> container = new ThreadLocal<Connection>();
    //配置说明,参考官方网址
    //http://blog.163.com/hongwei_benbear/blog/static/1183952912013518405588/
    static{
        dataSource.setUrl("jdbc:mysql://182.92.222.140:3306/idotest?useUnicode=true&characterEncoding=UTF-8");
        dataSource.setUsername("username");//用户名
        dataSource.setPassword("password");//密码
        dataSource.setInitialSize(2);
        dataSource.setMaxActive(20);
        dataSource.setMinIdle(0);
        dataSource.setMaxWait(60000);
        dataSource.setValidationQuery("SELECT 1");
        dataSource.setTestOnBorrow(false);
        dataSource.setTestWhileIdle(true);
        dataSource.setPoolPreparedStatements(false);
    }
 
    /**
     * 获取数据连接
     * @return
     */
    public static Connection getConnection(){
        Connection conn =null;
        try{
            conn = dataSource.getConnection();
            System.out.println(Thread.currentThread().getName()+"连接已经开启......");
            container.set(conn);
        }catch(Exception e){
            System.out.println("连接获取失败");
            e.printStackTrace();
        }
        return conn;
    }
    /***获取当前线程上的连接开启事务*/
    public static void startTransaction(){
        Connection conn=container.get();//首先获取当前线程的连接
        if(conn==null){//如果连接为空
            conn=getConnection();//从连接池中获取连接
            container.set(conn);//将此连接放在当前线程上
            System.out.println(Thread.currentThread().getName()+"空连接从dataSource获取连接");
        }else{
            System.out.println(Thread.currentThread().getName()+"从缓存中获取连接");
        }
        try{
            conn.setAutoCommit(false);//开启事务
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    //提交事务
    public static void commit(){
        try{
            Connection conn=container.get();//从当前线程上获取连接if(conn!=null){//如果连接为空,则不做处理
            if(null!=conn){
                conn.commit();//提交事务
                System.out.println(Thread.currentThread().getName()+"事务已经提交......");
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
 
 
    /***回滚事务*/
    public static void rollback(){
        try{
            Connection conn=container.get();//检查当前线程是否存在连接
            if(conn!=null){
                conn.rollback();//回滚事务
                container.remove();//如果回滚了,就移除这个连接
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    /***关闭连接*/
    public static void close(){
        try{
            Connection conn=container.get();
            if(conn!=null){
                conn.close();
                System.out.println(Thread.currentThread().getName()+"连接关闭");
            }
        }catch(SQLException e){
            throw new RuntimeException(e.getMessage(),e);
        }finally{
            try {
                container.remove();//从当前线程移除连接切记
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
    //简单使用方式
    public static void main(String[] args) throws SQLException {
        //select查询
        /*Connection conn = JDBCUtils.getConnection();
        PreparedStatement ps = conn.prepareStatement("SELECT 1");
        ResultSet rs = ps.executeQuery();
        JDBCUtils.close();*/
 
        //update,insert,delete操作
        Connection conn2 = JDBCUtils.getConnection();
        //开启事务1
        JDBCUtils.startTransaction();
        System.out.println("执行事务操作111111111111111....");
        JDBCUtils.commit();
        //开启事务2
        JDBCUtils.startTransaction();
        System.out.println("执行事务操作222222222222....");
        JDBCUtils.commit();
        JDBCUtils.close();
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
 
                public void run() {
                    Connection conn2 = JDBCUtils.getConnection();
                    for (int i = 0; i < 2; i++) {
                        JDBCUtils.startTransaction();
                        System.out.println(conn2);
                        System.out.println(Thread.currentThread().getName()+"执行事务操作。。。。。。。。。。。。。");
                        JDBCUtils.commit();
                    }
                    JDBCUtils.close();
                }
            }).start();
        }
         
    }
}

package com.atguigu.util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class JdbcUtilsFinal { private static DataSource dataSource; private static ThreadLocal<Connection> connectionThreadLocal = new ThreadLocal<>(); static{//静态代码块,在类加载和初始化时执行 //读取jdbc.properties配置文件 Properties properties = new Properties();//这是一个特殊的map。它的key,value都是String类型 //如果是在类路径(classpath)下,那么加载jdbc.properties文件,就需要用类加载器 ClassLoader classLoader = JdbcUtilsFinal.class.getClassLoader();//获取加载当前类的类加载器对象 try { //properties.load(classLoader.getResourceAsStream("jdbc.properties")); InputStream is = classLoader.getResourceAsStream("jdbc.properties"); if (is == null) { throw new ExceptionInInitializerError("jdbc.properties未找到"); } //创建数据库连接对象 dataSource = DruidDataSourceFactory.createDataSource(properties);//创建池的过程 } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection(){ try { Connection connection = connectionThreadLocal.get();//从当前线程自己的map中拿连接对象 if(connection == null){ connection = dataSource.getConnection(); connectionThreadLocal.set(connection);//存入当前线程自己的map中 } return connection; } catch (SQLException e) { throw new RuntimeException(e); //把编译时类型的异常 SQLException 重新包装为运行时异常的对象,抛出 //回头做项目时,会有一个全局处理异常的地方,统一处理 } } public static void freeConnection(){ try { Connection connection = connectionThreadLocal.get();//从当前线程自己的map中拿连接对象 if(connection != null) { connectionThreadLocal.remove();//从当前线程自己的map中删除它 connection.close(); } } catch (SQLException e) { throw new RuntimeException(e); } } } 08-Jun-2025 20:27:48.644 严重 [http-nio-8080-exec-7] com.alibaba.druid.pool.DruidDataSource.error {dataSource-1} init error java.sql.SQLException: url not set at com.alibaba.druid.pool.DruidDataSource.init(DruidDataSource.java:895) at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1376) at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1372) at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:109) at com.atguigu.util.JdbcUtilsFinal.getConnection(JdbcUtilsFinal.java:38) at com.atguigu.dao.BaseDAO.queryValue(BaseDAO.java:92) at com.atguigu.dao.UserDAOImpl.checkUsername(UserDAOImpl.java:15)
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值