JDBC学习(二)---------连接池和&DBUtils

JDBC连接池目的:主要解决数据库一直申请链接,释放连接所产生的资源浪费,提升代码性能。
获得连接和释放资源非常耗系统资源,通常使用连接池技术,共享Connection。通过池来管理Connection,重复利用。归还连接时调用close(),但是不是销毁连接,而是归还连接,将连接放在连接池中。
java为数据库连接提供的公共结构:java.sql.DataSoure。
常见的连接池:DBCP(占市场百分之十几)、C3P0(占80%以上)。
自定义简单连接池:

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;

import javax.sql.DataSource;

//自定义的工具类,有和数据库建立连接的方法。
import cn.jdbc.utils.CopyOfCopyOfJDBCUtils;

 

public class MyDataSource implements DataSource{
//1.创建一个容器用于存储Connection对象
	private static LinkedList<Connection> pool = new LinkedList<Connection>();
//2.创建5个链接放到容器中
	static {
		for (int i = 0; i < 5; i++) {
			Connection conn = CopyOfCopyOfJDBCUtils.getConnection();
			pool.add(conn);
		}
	}

	//重写获取连接的方法
	@Override
	public Connection getConnection() throws SQLException {
		Connection conn=null;
//		3.使用前先判断
		if(pool.size()==0){
//			4.如果池子里面没有,则在创建一些
			for (int i = 0; i < 5; i++) {
				conn = CopyOfCopyOfJDBCUtils.getConnection();
				pool.add(conn);
			}
		}
//		5.从池子中获取一个连接对象Connection
		conn=pool.remove(0);
//		移除的也是conn对象,将移除的对象返回,相当于拿到Connection对象。
		return conn;
	}
//	归还连接对象到连接池中去
	public void backConnection(Connection conn){
		pool.add(conn);
	}

注意:在创建类接口时会提示出现错误,也就是在写语句MyDataSource implements DataSource时,会报错。
此时选择添加没有实现的 方法选项,也就是Add unimplement methods。

自定义测试类:

import java.sql.Connection;
import java.sql.PreparedStatement;

import org.junit.Test;

import cn.jdbc.DataSource.MyDataSource;

public class TestMyDataSource {
//测试添加用户
	@Test
	public void testAddUser(){
		Connection conn =null;
		PreparedStatement pr=null;
//		1.创建自定义连接池对象
		
		MyDataSource dataSource=new MyDataSource();
		try {
//			2.从池子中获取连接
			conn =dataSource.getConnection();
			String sql="insert into tbl_user values(null,?,?)";
			pr=conn.prepareStatement(sql);
			pr.setString(1, "燕小六");
			pr.setString(2, "燕小六");
			int rows=pr.executeUpdate();
			if(rows>0){
				System.out.println("添加成功");
			}else{
				System.out.println("添加失败");
			}
		} catch (Exception e) {
			throw new RuntimeException();
		}finally{
			dataSource.backConnection(conn);
		}
	}
}

代码运行结果为:添加成功。
查看数据库用户燕小六的信息也出现在数据中。
修改重写close()方法。
需求:仍然调用close()方法,实现将资源归还到连接池,避免资源被真正的释放。
4种方法:
1.继承,子类继承父类,将父类的方法进行复写,从而进行增强。
适用前提:必须有父类,且存在继承关系。
2.【装饰者设计模式】,此设计模式专门用于增强方法。
使用前提:必须有接口,且需要将接口的所有方法都实现(缺点)
3.动态代理:在运行时动态的创建代理类,完成增强操作,与装饰者类似适用前提,必须有接口。
难点:需要反射技术。
4.字节码增强,运行时创建目标子类,从而增强。
常见第三方框架:cglib、javassist等。
这次使用第二种方法,装饰者设计模式。
自定义MyConnection,这是其中一部分代码,需要对close() 和prepareStatement(String sql)进行重写。

//1.实现同一个接口
public class MyConnection implements Connection {
//	3.定义一个变量
	private Connection conn;
	private LinkedList<Connection> pool;
//	2.编写一个构造方法,参数使用了面向对象的多态特性
	public MyConnection(Connection conn,LinkedList<Connection> pool){
		this.conn=conn;
		this.pool=pool;
	}

	@Override
	public void clearWarnings() throws SQLException {
		// TODO Auto-generated method stub
		
	}
//4.书写需要增强的方法
	@Override
	public void close() throws SQLException {
		pool.add(conn);
		
	}

//此方法必须覆盖,否则会出现空指针异常
	@Override
	public PreparedStatement prepareStatement(String sql) throws SQLException {
		// TODO Auto-generated method stub
		return conn.prepareStatement(sql);
	}

之后测试类

//使用改造过得方法,测试添加用户
	@Test
	public void testAddUser1(){
		Connection conn =null;
		PreparedStatement pr=null;
//		1.创建自定义连接池对象
		
		DataSource dataSource=new CopyOfMyDataSource();
		try {
//			2.从池子中获取连接
			conn =dataSource.getConnection();
			String sql="insert into tbl_user values(null,?,?)";
//			必须在自定义的Connection类中重写prepareStatement(sql)方法
			pr=conn.prepareStatement(sql);
			pr.setString(1, "燕小七");
			pr.setString(2, "燕小七");
			int rows=pr.executeUpdate();
			if(rows>0){
				System.out.println("添加成功");
			}else{
				System.out.println("添加失败");
			}
		} catch (Exception e) {
			throw new RuntimeException();
		}finally{
			CopyOfCopyOfJDBCUtils.release(conn, pr, null);
		}
	}

自定义的连接池,只用修改部分代码,调用MyConnection的方法即可`

//2.创建5个链接放到容器中
	static {
		for (int i = 0; i < 5; i++) {
			Connection conn = CopyOfCopyOfJDBCUtils.getConnection();
//			放入池子中的connection对象已经经过改造了
			MyConnection myconn=new MyConnection(conn,pool);
			pool.add(myconn);
		}
	}

	//重写获取连接的方法
	@Override
	public Connection getConnection() throws SQLException {
		Connection conn=null;
//		3.使用前先判断
		if(pool.size()==0){
//			4.如果池子里面没有,则在创建一些
			for (int i = 0; i < 5; i++) {
				conn = CopyOfCopyOfJDBCUtils.getConnection();
//				放入池子中的connection对象已经经过改造了
				MyConnection myconn=new MyConnection(conn,pool);
				pool.add(myconn);
			}
		}
//		5.从池子中获取一个连接对象Connection
		conn=pool.remove(0);
//		移除的也是conn对象,将移除的对象返回,相当于拿到Connection对象。
		return conn;

C3P0连接池:开源免费的连接池,目前使用的开源项目有:Spring、Hibernate等等,C3P0属于第三方工具,在使用是需要导入jar包。使用时还需要加载c3p0-config.xml配置文件(两种方法,一种加,一种不用加),一般都加。也支持.properties文件。
首先导包,方法步骤和导入jdbc包一样
其次在java工程的src文件中创建或者复制一份c3p0-config.xml配置文件。
测试c3p0连接池:只需要改动DataSource dataSource=new ComboPooledDataSource();即可。

import java.sql.Connection;
import java.sql.PreparedStatement;

import javax.sql.DataSource;

import org.junit.Test;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import cn.jdbc.utils.CopyOfCopyOfJDBCUtils;

public class TestC3P0 {
	//使用C3P0连接池,测试添加用户
	@Test
	public void testAddUser1(){
		Connection conn =null;
		PreparedStatement pr=null;
//		1.创建自定义连接池对象
		
		DataSource dataSource=new ComboPooledDataSource();
//		DataSource dataSource=new ComboPooledDataSource(oracle);
//		括号里面不加参数,定义默认的连接池对象,加参数则定义名字为参数的连接池对象
		try {
//			2.从池子中获取连接
			conn =dataSource.getConnection();
			String sql="insert into category values(?,?)";
//			必须在自定义的Connection类中重写prepareStatement(sql)方法
			pr=conn.prepareStatement(sql);
			pr.setString(1, "c005");
			pr.setString(2, "燕小五");
			int rows=pr.executeUpdate();
			if(rows>0){
				System.out.println("添加成功");
			}else{
				System.out.println("添加失败");
			}
		} catch (Exception e) {
			throw new RuntimeException();
		}finally{
			CopyOfCopyOfJDBCUtils.release(conn, pr, null);
		}
	}
}

C3P0工具类的抽取:

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0Utils {
//	c3p0工具类
	private static ComboPooledDataSource dataSource=new ComboPooledDataSource();
	
	public static DataSource getDataSource(){
		return dataSource;
	}
	
	public static Connection getConnection(){
		try {
			return dataSource.getConnection();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}
}

再测试:

@Test
	public void testAddUser2(){
		Connection conn =null;
		PreparedStatement pr=null;
		
		try {
//			2.从池子中获取连接
			conn =C3P0Utils.getConnection();
			String sql="insert into category values(?,?)";
//			必须在自定义的Connection类中重写prepareStatement(sql)方法
			pr=conn.prepareStatement(sql);
			pr.setString(1, "c006");
			pr.setString(2, "燕小六");
			int rows=pr.executeUpdate();
			if(rows>0){
				System.out.println("添加成功");
			}else{
				System.out.println("添加失败");
			}
		} catch (Exception e) {
			throw new RuntimeException();
		}finally{
			CopyOfCopyOfJDBCUtils.release(conn, pr, null);
		}
	}

DBCP连接池:配置文件名称.properties,不能编写中文。

JDBC简化工具包DBUtils目的:节省代码。

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

import cn.jdbc.utils.C3P0Utils;


//测试DUBtils工具类的增删改查
public class TestDBUtils {
//添加所有用户方法
	@Test
	public void testAddUser(){

		try {
//			1.创建核心类QuerryRunner
			QueryRunner qr=new QueryRunner(C3P0Utils.getDataSource());
//			2.编写sql语句
			String sql ="insert into category values(?,?)";
//			3.为占位符设置值
			Object[] params={"余淮","耿耿"};
//			4.执行添加操作
			int rows= qr.update(sql,params);
			if(rows>0){
				System.out.println("添加成功");
			}else{
				System.out.println("添加失败");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Test
	public void testDeleteUser(){

		try {
//			1.创建核心类QuerryRunner
			QueryRunner qr=new QueryRunner(C3P0Utils.getDataSource());
//			2.编写sql语句
			String sql ="delete from category where cid=?";
//			3.为占位符设置值
			Object[] params={"余淮"};
//			4.执行添加操作
			int rows= qr.update(sql,params);
			if(rows>0){
				System.out.println("删除成功");
			}else{
				System.out.println("删除失败");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Test
	public void testUpdateUserById(){

		try {
//			1.创建核心类QuerryRunner
			QueryRunner qr=new QueryRunner(C3P0Utils.getDataSource());
//			2.编写sql语句
			String sql ="update category set cname=? where cid=?";
//			3.为占位符设置值
			Object[] params={"燕子","c005"};
//			4.执行添加操作
			int rows= qr.update(sql,params);
			if(rows>0){
				System.out.println("修改成功");
			}else{
				System.out.println("修改失败");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值