使用jdbc訪問數據庫,每次建立連接,連接完成進行相應的操作後就對其進行關閉操作。每次訪問都需建立對數據庫的連接,很耗資源。就像剛建好一棟房子,進去住了幾天,就把它拆了重新建立,雖然可以建立,但耗很大資源。爲了防止這樣的事情發生,於是數據庫連接池產生了。
建立數據庫連接池是由第三方提供的jar包,C3P0或者DBCP的jar包都可以。
本人使用C3P0jar包自己做了一個C3P0Utils工具類,代碼如下:
package com.itheima.utils;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Utils {
private static DataSource ds=new ComboPooledDataSource();
/**
* 獲取數據庫連接
* @return 返回Connection
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
/**
* 獲取數據源
* @return
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 關閉數據庫
*/
public static void close(ResultSet rs,Statement ps,Connection con){
if(rs!=null){
try {
rs.close();
rs=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null){
try {
ps.close();
ps=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
con=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
有了C3P0Utls工具類,自定義自己的dbutils就方便多了。
首先,在對數據庫進行操作時,主要有增刪改查,其中,增刪改用一個方法update封裝就搞定,查詢涉及到把數據封裝到bean中,也可以用一個方法query搞定。
具體代碼如下:
package com.itheima.utils;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.itheima.dao.ResultSetHandler;
public class DbUtils {
private static DataSource ds=null;
public DbUtils(DataSource ds) {
super();
this.ds = ds;
}
/**
* 對數據庫進行增刪改操作
* @param sql SQL語句
* @param params 傳入的問號對應的參數
*/
public static void executeUpdate(String sql,Object...params){
Connection con=null;
PreparedStatement ps=null;
try {
con=ds.getConnection();
ps=con.prepareStatement(sql);
ParameterMetaData pmd=ps.getParameterMetaData();
int count=pmd.getParameterCount();
if(count>0){
if(params==null||params.length==0){
//參數爲空或者爲null,都不能匹配需要傳入的問號個數,則拋出異常
throw new IllegalArgumentException("參數不能爲null或者空");
}else if(params.length!=count){
System.out.println(count+"=="+params.length);
//參數的長度不匹配問號個數,也要拋出異常
throw new IllegalArgumentException("參數不匹配");
}
for(int i=0;i<count;i++){
//參數個數等於問號個數,則將問號設置爲參數
ps.setObject(i+1, params[i]);
}
}
ps.executeUpdate();
} catch (Exception e) {
throw new RuntimeException("操作失敗");
}finally{
C3P0Utils.close(null, ps, con);
}
}
/**
* 查詢單條記錄並封裝成對象
* @param sql 要執行的語句
* @param rsh 要封裝的BeanHeadler類,封裝的對象爲傳入的類字節碼
* @param params 查詢參數
* @return
*/
public static Object executeQuery(String sql,ResultSetHandler rsh,Object...params){
Connection con=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
con=ds.getConnection();
ps=con.prepareStatement(sql);
ParameterMetaData pmd=ps.getParameterMetaData();
int count=pmd.getParameterCount();
if(count>0){
if(params==null||params.length==0){
//參數爲空或者爲null,都不能匹配需要傳入的問號個數,則拋出異常
throw new IllegalArgumentException("參數不能爲null或者空");
}else if(params.length!=count){
System.out.println(count+"=="+params.length);
//參數的長度不匹配問號個數,也要拋出異常
throw new IllegalArgumentException("參數個數不匹配");
}
for(int i=0;i<count;i++){
//參數個數等於問號個數,則將問號設置爲參數
ps.setObject(i+1, params[i]);
}
}
rs=ps.executeQuery();
return rsh.handler(rs);
} catch (Exception e) {
throw new RuntimeException("操作失敗");
}finally{
C3P0Utils.close(rs, ps, con);
}
}
}
3.寫一個接口
package com.itheima.dao;
import java.sql.ResultSet;
public interface ResultSetHandler {
Object handler(ResultSet rs);
}
4.寫幾個實現類
1.
package com.itheima.dao.impl;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import com.itheima.dao.ResultSetHandler;
/**
* 自定義封裝數據庫查詢的結果集
* @author Administrator
*
*/
public class BeanHeadler implements ResultSetHandler {
private Class clazz;
public BeanHeadler(Class clazz){
this.clazz=clazz;
}
public Object handler(ResultSet rs) {
//定義Object對象
Object obj=null;
//分而治之,將rs中的結果集封裝到obj對象中
try {
if(rs.next()){
obj=clazz.newInstance();
//獲取結果集元數據
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
for(int i=0;i<count;i++){
//通過元數據獲取到每列的名字
String columnName=rsmd.getColumnName(i+1);
//通過列名獲取到列值
Object columnValue=rs.getObject(columnName);
//有了列名再通過反射獲取到類obj的屬性值
Field f=clazz.getDeclaredField(columnName);
f.setAccessible(true);
f.set(obj, columnValue);
}
}
return obj;
} catch (Exception e) {
throw new RuntimeException("查詢失敗");
}
}
}
2.
package com.itheima.dao.impl;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import com.itheima.dao.ResultSetHandler;
public class BeanListHeadler implements ResultSetHandler {
private Class clazz;
public BeanListHeadler(Class clazz){
this.clazz=clazz;
}
@Override
public Object handler(ResultSet rs) {
List list=new ArrayList();
try {
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
while(rs.next()){
Object obj=clazz.newInstance();
//獲取結果集元數據
for(int i=0;i<count;i++){
//通過元數據獲取到每列的名字
String columnName=rsmd.getColumnName(i+1);
//通過列名獲取到列值
Object columnValue=rs.getObject(columnName);
//有了列名再通過反射獲取到類obj的屬性值
Field f=clazz.getDeclaredField(columnName);
f.setAccessible(true);
f.set(obj, columnValue);
}
list.add(obj);
}
return list;
} catch (Exception e) {
throw new RuntimeException("查詢失敗");
}
}
}
通過以上幾個步驟,一個簡單的mydbutils大功告成,可以使用其靈活的對數據庫進行增刪改查了