java数据库连接池技术简单使用

JDBCDemo.java:
package com.itheima.jdbc;

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

import com.itheima.pool.MyPool;

public class JDBCDemo {

	public static void main(String[] args) {

		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		MyPool pool = new MyPool();
		try {
			conn = pool.getConnection();
			ps = conn.prepareStatement("select * from account");
			rs = ps.executeQuery();
			while(rs.next()) {
				String name = rs.getString(2);
				String salary = rs.getString(3);
				System.out.println(name + " : " + salary);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			//关闭数据库连接
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					rs = null;
				}
			}
			if(ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					ps = null;
				}
			}
			/*
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					rs = null;
				}
			}
			*/
			//这里不能关闭数据库连接对象connection,应该将其返还给数据库连接池
			pool.returnConn(conn);
		}
	}
}

MyPool.java:

package com.itheima.pool;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
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;

public class MyPool implements DataSource{

	//list集合保存数据库连接池中的connection对象
	private static List<Connection> pool = new LinkedList<Connection>();
	//静态代码块,用于初始化list集合,即初始化数据库连接池,创建5个connection对象保存其中以备使用
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			for(int i = 0; i < 5; i++) {
				Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
				pool.add(conn);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	@Override
	public PrintWriter getLogWriter() throws SQLException {
		return null;
	}
	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
	}
	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
	}
	@Override
	public int getLoginTimeout() throws SQLException {
		return 0;
	}
	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		return null;
	}
	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	//重写父类的getConnection()方法,返回数据库连接池中的一个connection对象,
	//如果数据库连接池中connection对象都已被使用,即都被取走未返还,则创建3个connection对象保存其中供以后使用
	@Override
	public Connection getConnection() throws SQLException {
		if(pool == null) {
			for(int i = 0; i < 3; i++) {
				Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
				pool.add(conn);
			}
		}
		return pool.remove(0);
	}
	//创建新方法,用于返回数据库连接对象connection,因为dao层用完数据库的连接后,不应该将其销毁,而是应该将其返还给数据库连接池
	public void returnConn(Connection conn) {
		pool.add(conn);
	}
	@Override
	public Connection getConnection(String username, String password)
			throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

}

以上代码是数据库连接池的简单使用,但是有一个问题就是当你使用数据库连接池技术时,你需要修改JDBCDemo.java文件中finally代码块中的代码,即conn对象在finally代码块里不应该通过conn.close();方法关闭,而是应该返还给数据库连接池。这里我们采用“动态代理”的方式,解决该问题,即finally代码块里依然调用conn.close();方法。

此时以上两个java文件的代码更改如下:

package com.itheima.jdbc;

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

import com.itheima.pool.MyPool;

public class JDBCDemo {

	public static void main(String[] args) {

		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		MyPool pool = new MyPool();
		try {
			conn = pool.getConnection();
			ps = conn.prepareStatement("select * from account");
			rs = ps.executeQuery();
			while(rs.next()) {
				String name = rs.getString(2);
				String salary = rs.getString(3);
				System.out.println(name + " : " + salary);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			//关闭数据库连接
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					rs = null;
				}
			}
			if(ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					ps = null;
				}
			}
			if(conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					conn = null;
				}
			}
		}
	}
}
package com.itheima.pool;

import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
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;

public class MyPool implements DataSource{

	//list集合保存数据库连接池中的connection对象
	private static List<Connection> pool = new LinkedList<Connection>();
	//静态代码块,用于初始化list集合,即初始化数据库连接池,创建5个connection对象保存其中以备使用
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			for(int i = 0; i < 5; i++) {
				Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
				pool.add(conn);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	@Override
	public PrintWriter getLogWriter() throws SQLException {
		return null;
	}
	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
	}
	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
	}
	@Override
	public int getLoginTimeout() throws SQLException {
		return 0;
	}
	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		return null;
	}
	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	//重写父类的getConnection()方法,返回数据库连接池中的一个connection对象,
	//如果数据库连接池中connection对象都已被使用,即都被取走未返还,则创建3个connection对象保存其中供以后使用
	@Override
	public Connection getConnection() throws SQLException {
		if(pool == null) {
			for(int i = 0; i < 3; i++) {
				Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
				pool.add(conn);
			}
		}
		final Connection conn = pool.remove(0);

		//使用动态代理改造close方法
		//newProxyInstance(类加载器, 要改造的conn对象所实现的所有接口,  匿名内部类)
		Connection proxy = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() {

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				if("close".equals(method.getName())) {
					//如果是close方法,我们进行重写
					returnConn(conn);
					return null;
				} else {
					//如果是其他方法,直接调用
					return method.invoke(conn, args);
				}
			}
		});
		System.out.println("获取一个连接对象,剩余连接对象:" + pool.size());
		return proxy;
	}
	//创建新方法,用于返回数据库连接对象connection,因为dao层用完数据库的连接后,不应该将其销毁,而是应该将其返还给数据库连接池
	public void returnConn(Connection conn) {
		pool.add(conn);
		System.out.println("返还一个连接对象,剩余连接对象:" + pool.size());
	}
	@Override
	public Connection getConnection(String username, String password)
			throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

}

运行结果:

获取一个连接对象,剩余连接对象:4
a : 1000.0
b : 1000.0
c : 1000.0
返还一个连接对象,剩余连接对象:5
时间: 2024-10-09 21:15:51

java数据库连接池技术简单使用的相关文章

Java数据库连接池详解

http://www.javaweb1024.com/java/JavaWebzhongji/2015/06/01/736.html 对于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式正是为了解决资源的频繁分配﹑释放所造成的问题.为解决我们的问题,可以采用数据库连接池技术.数据库连接池的基本思想就是为数据库连接建立一个"缓冲池".预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从"缓冲池"中取出一个,使用完毕之后再放回去

【Java】数据库连接池技术

JDBC的问题 在程序中,我们经常要建立与数据库的连接,之后再关闭这个连接.我们知道,数据库连接对象的创建是比较消耗系统性能的,这些频繁的操作势必会消耗大量的系统资源.因此我们需要采用更高效的数据库访问技术. 数据库连接池的概念 在JDBC2.0中提出了数据库连接池技术,它提供了javax.Sql.DataSource(数据源)接口,它负责建立与数据库的连接.通过客户之间共享一组连接,而不是在它们需要的时候为他们新建立连接,这样就可以改善资源的使用,提高应用程序的响应能力. 连接池技术的核心思想

关于c3p0数据库连接池的简单使用

在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤: 在主程序(如servlet.beans)中建立数据库连接. 进行sql操作 断开数据库连接. 这种模式开发,存在的问题: 普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s-1s的时间).需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接.这样的方式将会消耗大量的资源和时间.数据库的连接资源并没有得

java数据库连接池dbcp的使用

近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机 应用程序已从传统的桌面应用转到Web应用.基于B/S(Browser/Server)架构的3层开发模式逐渐取代C/S(Client/Server)架构的开发模式,成为开发企业级应用和电子商务普遍采用的技术. 在Java语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁, 即Java语言通过JDBC技术访问数据库.JDBC是一种"开放"的方案,它

java数据库连接池实现原理

一.为什么在连接数据库时要使用连接池 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.  一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的 性能低下. 数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并讲这些连接组成一个连接池(简单说:在一个"池"里放了好多半成品的数据库联接对象),由应用程序动态地对池中的连接进行申请.使用和释放.对于多于连接池中连接数的并发请求,应该在请求队列

[转帖]为什么HikariCP被号称为性能最好的Java数据库连接池,如何配置使用

为什么HikariCP被号称为性能最好的Java数据库连接池,如何配置使用 原创Clement-Xu 发布于2015-07-17 15:53:14 阅读数 57066  收藏 展开 HiKariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池. 原文地址:http://blog.csdn.net/clementad/article/details/46928621 官网:https://github.com/brettwooldridge/HikariCP 为何要使用H

Java数据库连接池

写了个 Java数据库连接池,具备基本的功能点: 1.对池中活动连接的重用. 2.池满时的适时等待. 3.对空闲连接的适时关闭. 抛砖引玉,不吝赐教. 源码文件 DBConnection.java 1 package db; 2 3 import java.sql.Connection; 4 import java.util.concurrent.atomic.AtomicBoolean; 5 6 /** 7 * 封装的连接 8 * @author Linkwork, [email protec

java 数据库连接池 Oracle版

首先应加入连接池和数据库连接的配置文件:数据库连接包:ojdbc6.jar数据库连接池包:commons-pool2-2.2.jar                       commons-dbcp2-2.0.jar数据库连接配置文件:config.properties使用连接池连接一定不要忘记关闭否则会很倒霉DBHelper 的写法 import java.io.IOException;import java.io.InputStream;import java.sql.Connectio

java数据库连接池性能对比

这个测试的目的是验证当前常用数据库连接池的性能. testcase Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.preparedStatement("select 1"); ResultSet rs = stmt.executeQuery(); while (rs.next()) { } rs.close(); stmt.close(); conn.close(); test c