dbutils的模擬實現(xiàn)
模擬DbUtils(QueryRunner)的實現(xiàn)恶耽,獲取一個數(shù)據(jù)庫連接(池),實現(xiàn)增刪改查操作聂儒,并實現(xiàn)結(jié)果集的簡單封裝(要求數(shù)據(jù)庫查詢結(jié)果的列名與bean的屬性名相同)
一灼擂、工具實現(xiàn)
1.工具使用類DBAssit.java
package com.itheima.dbassit;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class DBAssit {
private DataSource dataSource;
public DBAssit(DataSource dataSource) {
this.dataSource = dataSource;
}
/** 執(zhí)行增刪改的方法 */
public int update(String sql, Object... params) {
Connection conn = null;
PreparedStatement pstm = null;
try {
// 1. 得到連接
conn = dataSource.getConnection();
// 2. 使用連接好參數(shù)的sql語句創(chuàng)建預(yù)處理對象
pstm = conn.prepareStatement(sql);
// 3. 得到sql語句參數(shù)的源信息(有幾個層參數(shù),都什么類型的等)
ParameterMetaData pmd = pstm.getParameterMetaData();
// 4. 判斷語句中參數(shù)的個數(shù)和方法參數(shù)params的個數(shù)是否一致
int parameterCount = pmd.getParameterCount();
// 如果需要參數(shù)焰盗,則開始判斷
if (parameterCount > 0) {
if(params == null){
throw new NullPointerException("沒有sql語句執(zhí)行必須的參數(shù)");
}
if(params.length != parameterCount) {
throw new RuntimeException("參數(shù)的參數(shù)個數(shù)有誤璧尸!");
}
}
// 5. 給sql語句的參數(shù)賦值
for(int i=0;i<parameterCount;i++){
pstm.setObject(i+1, params[i]);
}
// 6. 執(zhí)行語句
int res = pstm.executeUpdate();
// 7. 返回執(zhí)行結(jié)果
return res;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
release(conn, pstm, null);
}
}
/** 查詢的方法 */
public Object query(String sql, ResultSetHandler rsh, Object... params) {
Connection conn = null;
PreparedStatement pstm = null;
ResultSet rs = null;
try {
// 1. 得到連接
conn = dataSource.getConnection();
// 2. 使用連接好參數(shù)的sql語句創(chuàng)建預(yù)處理對象
pstm = conn.prepareStatement(sql);
// 3. 得到sql語句參數(shù)的源信息(有幾個層參數(shù),都什么類型的等)
ParameterMetaData pmd = pstm.getParameterMetaData();
// 4. 判斷語句中參數(shù)的個數(shù)和方法參數(shù)params的個數(shù)是否一致
int parameterCount = pmd.getParameterCount();
// 如果需要參數(shù)熬拒,則開始判斷
if (parameterCount > 0) {
if(params == null){
throw new NullPointerException("沒有sql語句執(zhí)行必須的參數(shù)");
}
if(params.length != parameterCount) {
throw new RuntimeException("參數(shù)的參數(shù)個數(shù)有誤爷光!");
}
}
// 5. 給sql語句的參數(shù)賦值
for(int i=0;i<parameterCount;i++){
pstm.setObject(i+1, params[i]);
}
rs = pstm.executeQuery();
/** 封裝方法需要自己實現(xiàn) */
return rsh.handle(rs);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
release(conn, pstm, null);
}
}
private void release(Connection conn, PreparedStatement pstm, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (pstm != null) {
try {
pstm.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2. 結(jié)果集封裝接口
- ResultSetHandler.java
package com.itheima.dbassit;
import java.sql.ResultSet;
public interface ResultSetHandler<T> {
/** 結(jié)果集封裝的方法 */
Object handle(ResultSet rs);
}
- BeanHandler.java實現(xiàn)類
package com.itheima.dbassit.resultSetHandler;
import com.itheima.dbassit.ResultSetHandler;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
/** 有點 */
public class BeanHandler<T> implements ResultSetHandler<T> {
/** 被封裝的實體類的字節(jié)碼對象 */
private Class<T> domainClass;
public BeanHandler(Class<T> domainClass) {
this.domainClass = domainClass;
}
/** 結(jié)果集封裝的具體實現(xiàn)
* 此類實現(xiàn)的是吧一個結(jié)果集rs封裝到一個指定的實體類對象中
* 使用要求:(為了方便)
* 實體類中的屬性必須和表中的列名一致(sql語句查詢出來的列名一致)
*
* */
public T handle(ResultSet rs) {
try {
// 1. 創(chuàng)建一個實體類對象
T bean = domainClass.newInstance();
// 2. 判斷是否有結(jié)果集
if(rs.next()) {
// 3. 得到結(jié)果集rs中所有的列名
// 想要得到列名,得先得到結(jié)果集的源信息
ResultSetMetaData rsmd = rs.getMetaData();
// 得到源信息之后澎粟,還需要得到多少列
int columnCount = rsmd.getColumnCount();
// 遍歷列數(shù)
for (int i = 1; i<=columnCount; i++) {
// 得到每列的名稱
String columnName = rsmd.getColumnName(i);
// 列名就是實體類的屬性名稱蛀序,于是集可以使用列名得到實體類中屬性的【描述器】
PropertyDescriptor pd = new PropertyDescriptor(columnName, domainClass); //定義實體類中定義的描述器
// 獲取屬性的寫入方法(set方法)
Method method = pd.getWriteMethod();
// 獲取當前列名所對應(yīng)的值
Object columnValue = rs.getObject(columnName);
// 通過執(zhí)行方法吧得到的值給屬性附上
method.invoke(bean, columnValue);
}
}
// 返回封裝的對象
return bean;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
- BeanListHandler.java 實現(xiàn)類
package com.itheima.dbassit.resultSetHandler;
import com.itheima.dbassit.ResultSetHandler;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
public class BeanListHandler<T> implements ResultSetHandler<T> {
/** 被封裝的實體類的字節(jié)碼對象 */
private Class<T> domainClass;
public BeanListHandler(Class<T> domainClass) {
this.domainClass = domainClass;
}
/** 結(jié)果集封裝的具體實現(xiàn)
* 此類實現(xiàn)的是吧一個結(jié)果集rs封裝到一個指定的實體類對象中
* 使用要求:(為了方便)
* 實體類中的屬性必須和表中的列名一致(sql語句查詢出來的列名一致)
*
* */
public List<T> handle(ResultSet rs) {
try {
List<T> list = new ArrayList<T>();
// 2. 判斷是否有結(jié)果集
while(rs.next()) {
// 1. 創(chuàng)建一個實體類對象
T bean = domainClass.newInstance();
// 3. 得到結(jié)果集rs中所有的列名
// 想要得到列名,得先得到結(jié)果集的源信息
ResultSetMetaData rsmd = rs.getMetaData();
// 得到源信息之后活烙,還需要得到多少列
int columnCount = rsmd.getColumnCount();
// 遍歷列數(shù)
for (int i = 1; i<=columnCount; i++) {
// 得到每列的名稱
String columnName = rsmd.getColumnName(i);
// 列名就是實體類的屬性名稱徐裸,于是集可以使用列名得到實體類中屬性的【描述器】
PropertyDescriptor pd = new PropertyDescriptor(columnName, domainClass); //定義實體類中定義的描述器
// 獲取屬性的寫入方法(set方法)
Method method = pd.getWriteMethod();
// 獲取當前列名所對應(yīng)的值
Object columnValue = rs.getObject(columnName);
// 通過執(zhí)行方法吧得到的值給屬性附上
method.invoke(bean, columnValue);
}
list.add(bean);
}
// 返回封裝的對象
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
3.被封裝的javaBean
public class MyCount {
private int id;
private String name;
private Float money;
...
二、測試方法
public class Main {
public static void main(String[] args) throws Exception {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql:///spring_01");
ds.setUser("root");
ds.setPassword("abc123");
DBAssit dbAssit = new DBAssit((DataSource)ds);
Object obj = dbAssit.query("select * from account where id = ?",
new BeanHandler(MyCount.class), 1);
System.out.println(obj);
}
}