Java反射结合JDBC写的一个通用DAO

以前写反射只是用在了与设计模式的结合上,并没有考虑到反射可以与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;
	}
	
	
}




posted @ 2014-06-20 22:18  lvyahui  阅读(1087)  评论(0编辑  收藏  举报