JDBC-批处理-数据库连接池c3p0

一般步骤:
1.注册数据库驱动  
2.获取数据库连接
3.获取传输器   
4.利用传输器发送SQL到数据库执行,并返回执行结果
5.打印结果

6.释放资源

说明:一般情况会将1,2,和6,三步封装进JDBCUtils类中,并使用配置文件来存储driverClass、jdbcUrl、user、password等信息

必须用到的三个对象:Connection连接,Statement/PreparedStatement传输器,ResultSet结果集


下面是简单的代码实现

配置文件:

driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/jt_db
user=root
password=123456

JDBCUtils类

package JDBCUtils;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * 用于封装注册驱动,创建链接
 *
 */
public class JDBCUtils {
	
	private JDBCUtils(){
		//为了不让别人创建实例,私有化,这样可以在别的类中不用new而直接调用这个类中的static方法
		
	}
	//将读取配置文件的操作放在静态块中,程序运行只调用一次
	private static Properties p;
	static{
		//new配置文件对象
		 p = new Properties();
		//加载配置文件地址
		try {
			p.load(new FileInputStream(
				"src/main/resources/conf.properties"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
	//祖册驱动,获取连接
	public static Connection getConnection(){
		try {
			//1,注册驱动
			Class.forName(p.getProperty("driverClass"));
			//2,建立连接
			Connection conn=null;
			conn=DriverManager.getConnection(
					p.getProperty("jdbcUrl"), 
					p.getProperty("user"), 
					p.getProperty("password"));
			return conn;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * 用于关闭连接
	 * @param conn   关闭连接对象,如果关闭不了,就把它的引用置为空,让GC去回收对象
	 * @param stat	 关闭传输器对象,如果关闭不了,就把它的引用置为空,让GC去回收对象
	 * @param rs	关闭结果集对象,如果关闭不了,就把它的引用置为空,让GC去回收对象,preparedStatement对象是rs的子类,可直接传过来关闭
	 */
	public static void Close(Connection conn,Statement stat,ResultSet rs){
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				conn=null;
			}
		}
		if(stat!=null){
			try {
				stat.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				stat=null;
			}
		}
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				rs=null;
			}
		}
	}
}

测试类-- JDBC_CRUD  (CRUD创建,查询,更新,删除)

package com.tedu.jdbc;

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

import JDBCUtils.JDBCUtils;
/**
 * 单纯的使用Statement对象和PreparedStatement对象访问数据库进行查询,
 * 未使用批处理和数据库连接池c3p0/dbcp
 */

public class JDBC_CRUD {

	public static void main(String[] args) {
		sel1();
	}
	//一,使用statement对象进行数据库访问
	public static void sel(){
		Connection conn=null;
		Statement stat = null;
		ResultSet rs=null;
		//1,2,通过JDBCUtils注册驱动,获取链接
		conn=JDBCUtils.getConnection();
		try {
			//3,获取传输器对象
			stat=conn.createStatement();
			//4,创建sql语句,并执行
			String sql = "select * from t1";
			rs = stat.executeQuery(sql);
			while(rs.next()){
				int id = rs.getInt(1);
				String name=rs.getString(2);
				System.out.println(id+":"+name);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//未使用连接池,所以此处为直接关闭连接
			JDBCUtils.Close(conn, stat, rs);
		}
		
	}
	
	
	//二,使用preparedStatement对象进行数据库访问
	public static void sel1(){
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs = null;
		
		//1,2
		conn=JDBCUtils.getConnection();
		//3,创建sql骨架,
		String sql = "select * from t1 where id

JDBC_CRUD_Batch 类,简单实现批处理

package com.tedu.jdbc;

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

import JDBCUtils.JDBCUtils;
/**
 * 使用批处理插入记录
 *注意:使用批处理一定要注意事务的自动提交要关闭掉,最后执行完SQL要使用手动提交事务
 */
public class JDBC_CRUD_Batch {
	public static void main(String[] args) {
		inst_ps();
	}
	//一,使用Statement对象进行批处理
	public static void inst(){
		Connection conn=null;
		Statement stat=null;
		ResultSet rs=null;
		//1,2,注册驱动,获取链接
		conn = JDBCUtils.getConnection();
		try {
			//关闭事务自动提交,改用手动提交
			conn.setAutoCommit(false);
			//3,获取Statement传输器对象
			stat=conn.createStatement();
			String sql="insert into t1 values(null,'dct')";
			String sql1="insert into t1 values(null,'bfm')";
			String sql2="insert into t1 values(null,'hcz')";
			String sql3="insert into t1 values(null,'pgd')";
			String sql4="insert into t1 values(null,'nzt')";
			//添加到批处理中
			stat.addBatch(sql);
			stat.addBatch(sql1);
			stat.addBatch(sql2);
			stat.addBatch(sql3);
			stat.addBatch(sql4);
			//将批处理执行
			stat.executeBatch();
			//事务手动提交
			conn.commit();
			System.out.println("执行完毕!");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			JDBCUtils.Close(conn, stat, rs);
		}
	}
	
	//二、使用PreparedStatement对象进行批处理
		//注意:使用PreparedStatement对象要使用SQL骨架,一个骨架只能做CRUD其中一个功能,不够灵活,
		//如果用到的批处理中CRUD都 有,那么就使用Statement对象做批处理
	public static void inst_ps(){
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		//1,2,注册驱动,获取链接
		conn=JDBCUtils.getConnection();
		//3,创建PreparedStatement对象
		//3.1生成sql骨架
		String sql = "update t1 set name='NZT' where name=?";
		String sql1="insert into t1 values(null,?)";
		try {
			//关闭事务的自动提交
			conn.setAutoCommit(false);
			//将骨架传入preparedStatement对象中
			ps=conn.prepareStatement(sql1);
			for(int i=0;i<10;i++){
				//将骨架内容补全后,一个一个的添加到批处理中
				ps.setString(1, "NZT"+i);
				ps.addBatch();
			}
			//执行批处理
			ps.executeBatch();
			//手动提交事务
			conn.commit();
			System.out.println("执行完毕!");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			JDBCUtils.Close(conn, ps, rs);
		}
	}
}

自己写的数据库连接池--未优化

package com.tedu.poll;


import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;


import javax.sql.DataSource;


import JDBCUtils.JDBCUtils;
	/**
	 * 1,写一个类,实现 DataSource 接口
	 */
public class MyPool implements DataSource {
	
	/**
	 * 2,创建一个容器,当做连接池使用,这里用LinkedList
	 */
	private static List list=
			new LinkedList();
	
	/**
	 * 3,提供一个静态块,在程序启动时,初始化一批连接放在连接池中共享
	 */
	private static Connection conn;
	static{
		for (int i = 0; i < 5; i++) {
			 conn=JDBCUtils.getConnection();
			list.add(conn);
		}
	}
	/**
	 * 4,实现getConnection方法,用来获取连接池中的链接
	 */
	public Connection getConnection() throws SQLException {
		//如果连接池里面的连接拿完了,那就再次加入5个连接
		if(list.size()==0){
			for(int i=0;i<5;i++){
				conn=JDBCUtils.getConnection();
				list.add(conn);
			}
		}
		 conn = list.remove(0);//get()方法是获得,使用后集合里面还有,remove()方法是移除,拿完就没了
		System.out.println("取连接,数量"+list.size());
		return conn;
	}
	
	/**
	 *,5,还连接
	 */
	public void returnConn(Connection conn){
		try {
			//如果连接不是空的,并且连接没有被关闭,就将连接添加到连接池中
			if(conn!=null && !conn.isClosed()){
				
				list.add(conn);
				System.out.println("还连接,连接数"+list.size());
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

测试自定义连接池

package com.tedu.poll;

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

/**
 * 测试自定义连接池
 *
 */
public class TestMyTool {
	public static void main(String[] args) {
		//查询t1表中的ID为3的记录
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		MyPool p = new MyPool();
		try {
			conn=p.getConnection();
			//3,创建PreparedStatement对象
			String sql="select * from t1 where id=?";
			ps=conn.prepareStatement(sql);
			ps.setInt(1, 3);
			rs=ps.executeQuery();
			while(rs.next()){
				int id=rs.getInt(1);
				String name=rs.getString(2);
				System.out.println(id+":"+name);
						
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//这里归还连接,而不是关闭连接
			p.returnConn(conn);
		}
	}
	
}


使用c3p0数据库连接池,需要重新配置JDBCUtils类(在文尾)

package test;

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

import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
 * 使用c3p0连接池
 */
public class C3p0 {
	public static void main(String[] args) {
		    Connection conn=null;
		    PreparedStatement ps=null;
		    ResultSet rs=null;
		   //0,导入c3p0的jar包
		   //1,写c3p0的XML配置文件,放在源文件夹中,c3p0会自动扫描配置文件并应用,省去了1,注册驱动环节,不用管它
		      //但是文件名字必须为c3p0-config.xml,使用c3p0就不用再配置JDBCUtils中的getConnection方法了
		   //2,从c3p0连接池获取链接-->new一个连接池对象
		    ComboPooledDataSource pool = new ComboPooledDataSource();
		    try {
		    	//3,获取一个连接给conn
				conn=pool.getConnection();
				//4,创建SQL骨架,创建传输器对象
				String t1="t1";
				String sql="select * from "+t1;
				//4.1将骨架传过去
				ps=conn.prepareStatement(sql);				
				//4.2设置骨架参数,不可以直接传表名,但是可以在上面的SQL语句中进行字符串拼接
//				ps.setString(1, t1);
				//5,执行SQL语句
				rs=ps.executeQuery();
				//6,获取结果
				while(rs.next()){
					int id=rs.getInt(1);
					String name=rs.getString(2);
					System.out.println(id+":"+name);
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				//7,还连接,因为这里使用的是c3p0连接池,c3p0连接池对close方法进行了改造,
				//close方法自动变成了还连接,不再是关闭资源!!!这点要注意
				JDBCUtils.JDBCUtils.Close(conn, ps, rs);
			}
	}
}

*****************************************************************************

  使用C3P0连接池开发步骤

1、导入开发包

 

2、创建数据库连接池

ComboPooledDataSource cpds = new ComboPooledDataSource();      

3、设置数据库连接的基本信息

配置c3p0-config.xml配置文件

(1)方式一:

cpds.setDriverClass("com.mysql.jdbc.Driver");

cpds.setJdbcUrl("jdbc:mysql:///mydb1");

cpds.setUser("root");

cpds.setPassword("root");

(2)方式二:推荐!!

在类目录下(开发时可以放在src或者类似的源码目录(源码目录指的是fileànewàSource folder出来的文件夹,源码目录下可以新建包,普通文件夹下不可以)下), 添加一个c3p0-config.xml文件(文件名必须这样写), 配置内容如下:

JDBC-批处理-数据库连接池c3p0_第1张图片

(3)方式三:

在类目录下(开发时可以放在src或者类似的源码目录下), 添加一个c3p0.properties文件, 配置内容如下:

4,通过连接池实例调用getConnection方法获取连接!

JDBC-批处理-数据库连接池c3p0_第2张图片

5,最后调用连接对象上的close方法,用来将连接还回连接池中

***********************************************************************************************************************

重新配置JDBCUtils类,使用c3p0数据库连接池之后,各个类更为简单了

package com.tedu.utils;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
 * 使用c3p0数据库连接池后,这个类就只剩下关闭资源的功能
 * 其他功能已经在测试类中铺设好,使用c3p0更为简单一些
 */
public class JDBCUtils2 {


	private JDBCUtils2(){//为了不让别人创建实例,私有化
		
	}
	
	/**
	 * 将制定的资源关闭(释放)
	 * @param conn   链接对象
	 * @param stat	 传输器对象
	 * @param rs	 结果集对象
	 */
	public static void close(Connection conn,Statement stat,ResultSet rs){
		if(rs !=null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				rs=null;
			}
		}
		if(stat != null){
			try {
				stat.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				stat=null;
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				conn=null;
			}
		}
	}
}


你可能感兴趣的:(JDBC-批处理-数据库连接池c3p0)