Java中数据库连接池(数据源)操作

本文介绍如何使用C3P0连接池优化数据库操作,详细讲解了连接池的作用、使用步骤及工具类代码,阐述了为何需要手动关闭Statement和ResultSet,确保代码的健壮性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用jdbc时,每操作一次都需要获取连接,用完后便将其释放、销毁。
选择利用连接池来优化curd操作。
连接池:管理数据库的连接,提高项目的性能。
作用:在连接池初始化的时候存入一定数量的连接,用的时候通过方法获取,不用的时候归还即可。
接口:所有的连接池必须实现 javax.sql.DataSource 接口。

c3p0使用步骤:

  • 导入jar包
  • 使用api
    a. 硬编码(不推荐)
    new ComboPooledDataSource();
    b. 配置文件
    配置文件名称:c3p0.properties 或者 c3p0-config.xml
    配置文件的路径:src下
    编码:
new  ComboPooledDataSource();  //使用默认的配置
new  ComboPooledDataSource(String configName);  //使用命名的配置,若配置找不到则使用默认配置

工具类代码:

package com.cdf.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class DataSourceUtils {
   private static ComboPooledDataSource ds = new ComboPooledDataSource();
   private static ThreadLocal<Connection> tl=new ThreadLocal<>();
   
   /**
    * 从线程中获取连接
    * @return
    * @throws SQLException
    */
   public static Connection getConnection() throws SQLException {
      //从线程中获取conneciton
      Connection conn = tl.get();
      if(conn==null){
         conn=ds.getConnection();
         //和当前线程绑定
         tl.set(conn);
      }
      return conn;
   }

   // 获取数据源
   public static DataSource getDataSource() {
      return ds;
   }

   // 释放资源
   public static void closeResource( Statement st, ResultSet rs) {
      closeResultSet(rs);
      closeStatement(st);
   }
   
   // 释放资源
   public static void closeResource(Connection conn, Statement st, ResultSet rs) {
      closeResource(st, rs);
      closeConn(conn);
   }

   // 释放 connection
   public static void closeConn(Connection conn) {
      if (conn != null) {
         try {
            conn.close();
            //和线程解绑
            tl.remove();
         } catch (SQLException e) {
            e.printStackTrace();
         }
         conn = null;
      }
   }

   // 释放 statement ctrl + shift + f 格式化代码
   public static void closeStatement(Statement st) {
      if (st != null) {
         try {
            st.close();
         } catch (SQLException e) {
            e.printStackTrace();
         }
         st = null;
      }
   }

   // 释放结果集
   public static void closeResultSet(ResultSet rs) {
      if (rs != null) {
         try {
            rs.close();
         } catch (SQLException e) {
            e.printStackTrace();
         }
         rs = null;
      }
   }
   
   
   //开启事务
   public static void startTransaction() throws SQLException{
      getConnection().setAutoCommit(false);
   }
   
   /**
    * 事务提交且释放连接
    */
   public static void commitAndClose(){
      Connection conn = null;
      try {
         conn=getConnection();
         //事务提交
         conn.commit();
         //关闭资源
         conn.close();
         //解除版定
         tl.remove();
      } catch (SQLException e) {
         e.printStackTrace();
      }
   }
   
   /**
    * 事务回滚且释放资源
    */
   public static void rollbackAndClose(){
      Connection conn = null;
      try {
         conn=getConnection();
         //事务回滚
         conn.rollback();
         //关闭资源
         conn.close();
         //解除版定
         tl.remove();
      } catch (SQLException e) {
         e.printStackTrace();
      }
   }
}

为什么要关闭Statement 和 ResultSet

线程从外界获取一个conn,然后创建自己地stmt,rs,然后执行逻辑操作,然后将conn返回给pool。 如果程序员忘记手动关地话。当这个线程执行完以后stmt,rs都成垃圾,当他们被垃圾搜集地时候,gc会替我们把它们给关闭地。这就是很多代码没有关闭,仍然正常运行。但是这样会有一个潜在地问题。就是gc无法确定什么时候运行。如果free地内存很多,很可能有些gc就不会被启动,这样stmt迟迟没有被关闭,执行一段时间会报错。所以健壮地代码应该手工把rs,stmt都关闭

关闭顺序最优:ResultSet -> Statement -> connection

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值