前面我们写了集中获取数据库的方法,这个方法其实是很消耗内存的也很消耗时间。他每次只能供应一个用户去取(用)数据库连接,这样很不方便;要是现在同时有很多人(人数在数据库连接上限以内)需要访问数据库的话该怎么办??
今天我们来看看数据连接池,有句话叫做“弱水三千,只取一瓢”;我们把连接在之前的基础上就给他多创建一些,把他装到一个池子里面;用户需要的时候我们就让他去取,用完了再让他归还。连接池大概就是这样一个原理
今天这个Demo
我们有一个java中的propertie文件 [db.propertie]:里面主要记录了关于获取数据库的一些东西,如驱动地址,数据库的地址,用户名密码。
还有一个记录静态值的java类Consts:这个类里面主要是记录了上面propertie里面的“键”,因为propertie里面是采用了键值对的形式存放的。
最后两个java类connectionpool,DBHelper:他们一个是连接池,连一个是对连接池的操作案例。
先来看看db.propertie文件里面的存放格式[eclipse里面也有相应的插件]:
db.propertie文件[左边:键,右边:值]:
driverName=com.mysql.jdbc.Driver
userName=root
passWord=123456
url=jdbc:mysql://127.0.0.1:3306/invoicing
Consts 静态值类:
package com.****.iis.framework.consts;
/**
* @author YangJing
*
*/
public class Consts {
public Consts() {
}
public static final String FILEPATH = "db.properties";
public static final String DRIVER = "driverName";
public static final String URL = "url";
public static final String USERNAME = "userName";
public static final String PASSWORD = "passWord";
}
Connectionpool类:
package com.****.iis.framework.db;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Properties;
import com.****.iis.framework.consts.Consts;
import com.****.iis.framework.consts.MessageConsts;
import com.****.iis.framework.exception.SystemException;
/**
* @author YangJing
*
*/
public class ConnectionPool {
//创建properties实例
static Properties p = new Properties();
//创建LinkedList对象用来存放数据库连接对象
private static LinkedList<Connection> connectionpool = new LinkedList<Connection>();
//数据库连接最小值
private int minCount = 5;
//数据库连接最大值
private int maxCount = 20;
//获取数据库连接时的计数器
private int currentCount = 0;
//静态块—>加载数据库驱动
static{
try {
// 从输入流中读取属性列表<加载db.propertie文件>
p.load(ConnectionPool.class.getResourceAsStream(Consts.FILEPATH));
//加载数据库驱动
Class.forName(p.getProperty(Consts.DRIVER));
} catch (ClassNotFoundException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_DBERROR, e);
} catch (FileNotFoundException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_FILENOTFOUNDERROR);
} catch (IOException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_FINEIOERROR);
}
}
//用构造方法向连接池里面添加数据库连接
public ConnectionPool() {
for (int i = 0; i < minCount; i++) {
connectionpool.addLast(this.createConnection());
}
}
//获取数据库连接
public Connection getConnection() throws SystemException{
//synchronized 关键字 表示方法加锁
synchronized (connectionpool) {
currentCount ++;
//如果连接不够用的时候就在创建连接
if(minCount >= currentCount){
return connectionpool.removeFirst();
}else if(maxCount >= currentCount){
return this.createConnection();
}
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_DBUSEERROR);
}
}
//创建数据库连接
private Connection createConnection() throws SystemException{
try {
//getProperty方法是为了用指定的键在此属性列表中搜索属性
return DriverManager.getConnection(p.getProperty(Consts.URL),p.getProperty(Consts.USERNAME),p.getProperty(Consts.PASSWORD));
} catch (SQLException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_DBCONNECTERROR);
}
}
//将使用过的连接放回到连接池中
public void freeResource(Connection conn){
currentCount --;
connectionpool.addLast(conn);
}
}
DBHelper 类:
package com.****.iis.framework.db;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.****.iis.framework.consts.MessageConsts;
import com.****.iis.framework.entity.UserInfo;
import com.****.iis.framework.exception.SystemException;
/**
* Class Description: 提供多个数据库操作方法
* 获取多条数据 获得单条数据 添加数据 删除数据 更新数据
* @author YangJing
*
*/
public class DBHelper {
protected Connection conn = null;
protected PreparedStatement ps = null;
protected ResultSet rs = null;
//创建连接池对象
private static ConnectionPool connectionPool = new ConnectionPool();
/**
* @author YangJing
*
*/
public DBHelper() {
conn = connectionPool.getConnection();
}
/**
* 添加对象到数据库
*
* @param sql 要执行的SQL语句
*
* @param objects SQL语句中所需要的参数列表
*
* @return 执行之后影响的行数
*/
public int addObjectInfo(String sql,Object...objects)throws SystemException{
int num = 0;
try {
ps = conn.prepareStatement(sql);
//参数元数据
ParameterMetaData parame = ps.getParameterMetaData();
if (objects != null && objects.length > 0) {
//循环为山下文对象赋值
for (int i = 0; i < parame.getParameterCount(); i++) {
ps.setObject(i+1, objects[i]);
}
num = ps.executeUpdate();
}else{
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_ARGUMENTERROR);
}
} catch (SQLException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_OPERATION, e);
}finally{
connectionPool.freeResource(conn);
}
return num;
}
/**
* 根据SQL语句和对象执行数据库查询,将单个对象的结果返回
*
* @param sql
* 要执行的SQL语句
* @param clazz
* 要操作的对象
* @param objects
* @return 对象在数据库中的信息
*/
public <T> T queryObjectInfoByCondition(String sql, Class<T> clazz,
Object...objects) throws SystemException {
T t = null;
try {
ps = conn.prepareStatement(sql);
// 参数元数据
ParameterMetaData parame = ps.getParameterMetaData();
if (objects != null && objects.length > 0) {
// 循环为上下文对象赋值
for (int i = 0; i < parame.getParameterCount(); i++) {
ps.setObject(i + 1, objects[i]);
}
} else {
throw new SystemException(
MessageConsts.ERROR_FRAMEWORK_ARGUMENTERROR);
}
// 执行查询,并返回结果集
rs = ps.executeQuery();
// 获取User里面的所有的公开方法
Method[] methods = clazz.getMethods();
while (rs.next()) {
t = clazz.newInstance();
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
// 现在利用元数据来拼接出一个和对象中方法是一样的方法名出来
String columnName = rs.getMetaData().getColumnLabel(i + 1);
String method = "set" + columnName;
// 遍历每一个方法,并利用反射调用相同的方法
for (Method m : methods) {
if (method.equals(m.getName())) {
m.invoke(t, rs.getObject(rs.getMetaData()
.getColumnName(i + 1)));
}
}
}
}
} catch (SQLException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_OPERATION, e);
} catch (InstantiationException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_INITIALIZE);
} catch (IllegalAccessException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_ILLEGALOPERATION);
} catch (IllegalArgumentException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORL_ILLEGALARGUMENT);
} catch (InvocationTargetException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORL_BADTREE);
}finally{
connectionPool.freeResource(conn);
}
return t;
}
public int updateObjectInfo(String sql, Object...objects)throws SystemException{
int num = 0;
try {
ps = conn.prepareStatement(sql);
//参数元数据
ParameterMetaData parame = ps.getParameterMetaData();
if (objects != null && objects.length > 0) {
//循环为上下文对象赋值
for (int i = 0; i < parame.getParameterCount(); i++) {
ps.setObject(i+1, objects[i]);
}
num = ps.executeUpdate();
}else{
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_ARGUMENTERROR);
}
} catch (SQLException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_OPERATION, e);
}finally{
connectionPool.freeResource(conn);
}
return num;
}
public <T> T querObjectInfo(String sql,Class<T> clazz)throws SystemException{
T t = null;
try {
ps = conn.prepareStatement(sql);
//执行查询,并返回结果集
rs=ps.executeQuery();
//获取传进来类的所有公开方法
Method[] methods = clazz.getMethods();
while(rs.next()){
t = clazz.newInstance();
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
//利用元数据来拼接出一个和对象中方法一样的方法明出来
String columnName = rs.getMetaData().getColumnLabel(i + 1);
String method = "set" + columnName;
for (Method m : methods) {
if(method.equals(m.getName())){
m.invoke(t, rs.getObject(rs.getMetaData().getColumnName(i + 1)));
}
}
}
}
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}finally{
connectionPool.freeResource(conn);
}
return t;
}
public <T> List<T> queryObjectsInfo(String sql, Class<T> clazz)
throws SystemException {
List<T> list = new ArrayList<T>();
try {
ps = conn.prepareStatement(sql);
// 执行查询,并返回结果集
rs = ps.executeQuery();
// 获取User里面的所有的公开方法
Method[] methods = clazz.getMethods();
T t = null;
while (rs.next()) {
t = clazz.newInstance();
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
// 现在利用元数据来拼接出一个和对象中方法是一样的方法名出来
String columnName = rs.getMetaData().getColumnLabel(i + 1);
String method = "set" + columnName;
// 遍历每一个方法,并利用反射调用相同的方法
for (Method m : methods) {
if (method.equals(m.getName())) {
m.invoke(t, rs.getObject(rs.getMetaData()
.getColumnName(i + 1)));
}
}
}
list.add(t);
}
} catch (SQLException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_OPERATION, e);
} catch (InstantiationException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_INITIALIZE);
} catch (IllegalAccessException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORK_ILLEGALOPERATION);
} catch (IllegalArgumentException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORL_ILLEGALARGUMENT);
} catch (InvocationTargetException e) {
throw new SystemException(MessageConsts.ERROR_FRAMEWORL_BADTREE);
}finally{
connectionPool.freeResource(conn);
}
return list;
}
//归还数据库连接
public static void getcolse(ResultSet rs,Statement st,Connection conn) throws SQLException{
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
connectionPool.freeResource(conn);
}
}
}