以前寫反射只是用在了與設計模式的結合上,並沒有考慮到反射可以與DAO結合。也是一個偶然的機會,被正在上培訓的老師點到這個問題,才考慮到這個可能性,於是上網參考各種代碼,然後自己動手開發了一個通用DAO。
大家除學JDBC時,也會有這種感觸,一般寫的DAO只能用在一張表上,不能通用,如果你的程序有多張表,就需要寫多個DAO,或者使用一些複雜設計來達到這個目的。而這個反射方式實現的DAO,就不需要很複雜的設計,就可以實現DAO的通用。
這個通用是有前提的,就是DAO接受的參數必須是絕對符合JavaBean標準的對象。而且JavaBean的屬性類型,必須跟數據庫中表的數據類型保持一致。否則就會出問題,下面貼出代碼,寫得不好,別見怪
package com.sldll.cms.dao;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
//0oO
public class GeneralDAO {
//---------------------------------查詢部分--------------------------------------------------------------------------
/**
* 查詢所有記錄
* @param obj 表對應的JavaBean對象
* @return 所有記錄構成的list
* @throws Exception
*/
public List<Object> findAll(Object obj) throws Exception {
List<Object> list = new ArrayList<Object>();
ResultSet rs = null;
try {
// 獲取數據庫連接
Statement stmt = DBConnectionManager.getConnection()
.createStatement();
// 構建sql語句
String tableName = obj.getClass().getName();
tableName = tableName.substring(tableName.lastIndexOf(".") + 1);
String sql = "select * from " + tableName;
// 執行sql語句
rs = stmt.executeQuery(sql);
while (rs.next()) {
list.add(createObj(rs, obj));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
} finally {
// 關閉連接
if (rs != null) {
rs.close();
}
DBConnectionManager.closeConnection();
}
return list;
}
/**
* 對指定的表執行指定的sql查詢語句
* @param obj
* 以該表對應的JavaBean對象決定表
* @param query
* 要對該表執行的sql語句
* @return
* @throws Exception
*/
public List<Object> findByNameQuery(Object obj, String query) throws Exception {
// TODO Auto-generated method stub
List<Object> list = null;
try {
Statement sql_statement = DBConnectionManager.getConnection()
.createStatement();
//執行傳遞的sql語句
ResultSet rs = sql_statement.executeQuery(query);
list = new ArrayList<Object>();
if (rs != null) {
while (rs.next()) {
list.add(createObj(rs, obj));
}
}
return list;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
} finally {
DBConnectionManager.closeConnection();
}
}
/**
* 按條件對指定表進行查詢
* @param obj
* 以該表對應的JavaBean對象決定表
* @param condition
* 查詢的條件,key:條件 value:值
* @param isFuzzzy
* 是否支持模糊查詢
* @return
* @throws Exception
*/
public List<Object> findByNameQuery(Object obj, Map<Object,Object> condition,boolean isFuzzy) throws Exception {
List<Object> list = new ArrayList<Object>();
try {
String tablename = getTableName(obj);
StringBuilder sb = new StringBuilder("select * from " + tablename);
PreparedStatement state = null;
if(isFuzzy){
addFuzzyConditionString(sb, condition);
}
else{
addConditionString(sb, condition);
}
state = DBConnectionManager.getConnection().prepareStatement(sb.toString());
state = setSqlValue(state, condition,isFuzzy);
ResultSet rs = state.executeQuery();
if (rs != null) {
while (rs.next()) {
list.add(createObj(rs, obj));
}
}
return list;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
} finally {
DBConnectionManager.closeConnection();
}
}
//-------------------------------------創建部分--------------------------------------------------------------------------
/**
* 在數據庫裏新建一條記錄
* @param obj
* 描述記錄的對象,必須是數據庫中某張表對應的JavaBean對象
* @return
* 新建成功返回真,否則返回假
* @throws Exception
*/
public boolean create(Object obj) throws Exception{
// 獲取數據庫連接
try {
// 構建sql語句
Map<Object, Object> map = getObjectFieldValue(obj);
String tableName = obj.getClass().getName();
tableName = tableName.substring(tableName.lastIndexOf(".") + 1);
StringBuilder sb = new StringBuilder("insert into " + tableName);
addCreateString(sb, map);
PreparedStatement stmt = DBConnectionManager.getConnection()
.prepareStatement(sb.toString());
setSqlValue(stmt, map,false);
int count = stmt.executeUpdate();
if(count>0){
return true;
}
else{
return false;
}
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
DBConnectionManager.closeConnection();
}
}
//-------------------------------------刪除部分----------------------------------------------------------------------------
/**
* 刪除表中所有記錄
* @param obj
* JavaBean對象,決定要刪除的是哪張表
* @return
* 刪除成功返回真,否則返回假
*/
public boolean deleteAll(Object obj) throws Exception{
String delete_sql = "delete from "+getTableName(obj);
PreparedStatement pstmt;
try {
pstmt = DBConnectionManager.getConnection().prepareStatement(delete_sql);
int count = pstmt.executeUpdate();
if(count>0){
return true;
}
else{
return false;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
}
finally{
DBConnectionManager.closeConnection();
}
}
/**
* 在指定表中刪除給定ID的記錄
* @param obj
* 表示要刪除的表
* @param condition
* 刪除的條件 key:字段(一般爲字符串) value:值
* @return
*/
public boolean delete(Object obj,Map<Object,Object> condition) throws Exception{
//構建sql語句
StringBuilder sb = new StringBuilder("delete from "+getTableName(obj));
addConditionString(sb, condition);
try {
PreparedStatement pstmt = DBConnectionManager.getConnection().prepareStatement(sb.toString());
setSqlValue(pstmt, condition,false);
int count = pstmt.executeUpdate();
if(count > 0){
return true;
}
else{
return false;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
}
finally{
DBConnectionManager.closeConnection();
}
}
//-------------------------------------更新部分----------------------------------------------------------------------------
/**
* 更新指定表的記錄
* @param obj
* 用來確定表的Java對象
* @param map
* 要設置的字段值,key:字段(字符串),value:值
* @param condition
* 篩選條件
* @return
*/
public boolean update(Object obj,Map<Object,Object> map,Map<Object, Object>condition) throws Exception {
StringBuilder sb = new StringBuilder("update "+getTableName(obj));
addSetString(sb,map);
addConditionString(sb, condition);
try {
PreparedStatement pstmt = DBConnectionManager.getConnection().prepareStatement(sb.toString());
List<Object> values = new ArrayList<Object>();
getValuesToList(values,map);
getValuesToList(values, condition);
setSqlValue(pstmt, values);
int count = pstmt.executeUpdate();
if(count > 0){
return true;
}
else{
return false;
}
} catch ( Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
}
finally{
DBConnectionManager.closeConnection();
}
}
private List<Object> getValuesToList(List<Object> values,Map<Object, Object> map) {
for (Iterator<Object> it = map.keySet().iterator(); it.hasNext();) {
Object value = map.get(it.next());
values.add(value);
}
return values;
}
/**
* 獲取JavaBean對象的字段值放到容器中
* @param obj
* JavaBean對象
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private Map<Object, Object> getObjectFieldValue(Object obj)
throws IllegalAccessException, InvocationTargetException {
Map<Object, Object> map = new HashMap<Object,Object>();
Field fields[] = obj.getClass().getFields();
Method methods[] = obj.getClass().getMethods();
// 給字段設置值
for (int i = 0; i < fields.length; i++) {
// 用字段的名字構建set方法的名字
String fieldName = fields[i].getName();
String methodName = "get" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
// 查找對應的方法
Method method = null;
for (int j = 0; j < methods.length; j++) {
if (methods[j].getName().equals(methodName)) {
method = methods[j];
break;
}
}
// 如果存在這個方法
if (method != null) {
// 開始執行方法,獲取當前的JavaBean對象字段值
Object value = method.invoke(obj, new Object[] { });
map.put(fieldName, value);
}
}
return map;
}
private void addSetString(StringBuilder sb, Map<Object, Object> map) {
// TODO Auto-generated method stub
if (!map.isEmpty()) {
sb.append(" set ");
for (Iterator<Object> it = map.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
if (null == key) {
continue;
}
sb.append(key+"=?,");
}
sb.deleteCharAt(sb.lastIndexOf(","));
System.out.println(sb.toString());
}
}
/**
* 在現有sql創建語句後面追加字段名和佔位符
* @param sb
* @param map
*/
private void addCreateString(StringBuilder sb,Map<Object, Object> map) {
// TODO Auto-generated method stub
sb.append("(");
int count = 0;
for (Iterator<Object> it = map.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
if (null == key) {
continue;
}
sb.append(key + ",");
count++;
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(") values(");
for (int i = 0; i < count; i++) {
sb.append("?,");
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(")");
System.out.println(sb.toString());
}
/**
* 在現有sql查詢語句後面追加判斷條件
* @param sb where之前的sql
* @param condition 條件(key:字段名;value:值)
* @return 使用佔位符的sql語句
*/
private String addConditionString(StringBuilder sb, Map<Object,Object> condition) {
if (!condition.isEmpty()) {
sb.append(" where ");
int i = 0;
for (Iterator<Object> it = condition.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
if (null == key) {
continue;
}
if (i != 0) {
sb.append(" and ");
}
if (key.indexOf("<") != -1 || key.indexOf(">") != -1
|| key.indexOf("=") != -1) {
sb.append(key + "?");
} else {
sb.append(key + "=" + "?");
}
i++;
}
}
System.out.println(sb.toString());
return sb.toString();
}
private String addFuzzyConditionString(StringBuilder sb,Map<Object,Object>condition) {
if (!condition.isEmpty()) {
sb.append(" where ");
int i = 0;
for (Iterator<Object> it = condition.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
if (null == key) {
continue;
}
if (i != 0) {
sb.append(" or ");
}
sb.append(key + " like " +"?");
i++;
}
}
System.out.println(sb.toString());
return sb.toString();
}
/**
* 設置現有sql語句的佔位符的值
* @param state
* @param map
* @return
* @throws SQLException
*/
private PreparedStatement setSqlValue(PreparedStatement state, Map<Object,Object> map,boolean isFuzzy)
throws SQLException {
if (!map.isEmpty()) {
int i = 1;
for (Iterator<Object> it = map.keySet().iterator(); it.hasNext();) {
Object value = map.get(it.next());
if(isFuzzy){
state.setObject(i++, "%"+value+"%");
}else{
state.setObject(i++, value);
}
}
}
return state;
}
private PreparedStatement setSqlValue(PreparedStatement state, List<Object> values)
throws SQLException {
if (!values.isEmpty()) {
int i = 1;
for (Iterator<Object> it = values.iterator(); it.hasNext();) {
Object value = it.next();
state.setObject(i++, value);
}
}
return state;
}
private String getTableName(Object obj) {
String tablename = obj.getClass().getName();
tablename = tablename.substring(tablename.lastIndexOf(".") + 1);
return tablename;
}
// 利用反射構建對象
private Object createObj(ResultSet rs, Object obj)
throws Exception {
// TODO Auto-generated method stub
Object object = obj.getClass().newInstance();
// 獲取字段
Field fields[] = obj.getClass().getFields();
// 獲取方法
Method methods[] = obj.getClass().getMethods();
// 給字段設置值
for (int i = 0; i < fields.length; i++) {
// 用字段的名字構建set方法的名字
String fieldName = fields[i].getName();
String methodName = "set" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
// 查找對應的方法
Method method = null;
for (int j = 0; j < methods.length; j++) {
if (methods[j].getName().equals(methodName)) {
method = methods[j];
break;
}
}
// 如果存在這個方法
if (method != null) {
// 開始執行方法,爲當前的JavaBean對象字段設置值
Object value = rs.getObject(fieldName);
method.invoke(object, new Object[] { value });
}
}
return object;
}
}