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

简介: 以前写反射只是用在了与设计模式的结合上,并没有考虑到反射可以与DAO结合。也是一个偶然的机会,被正在上培训的老师点到这个问题,才考虑到这个可能性,于是上网参考各种代码,然后自己动手开发了一个通用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;
	}
	
	
}




目录
相关文章
|
3月前
|
Java 关系型数据库 数据库连接
JDBC:Java与数据库的“黄金搭档”,为何它如此重要?
JDBC:Java与数据库的“黄金搭档”,为何它如此重要?
47 8
|
3月前
|
Java 数据库连接 API
JDBC:Java数据库连接的“黑科技”大揭秘
JDBC:Java数据库连接的“黑科技”大揭秘
37 7
|
23天前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
15 0
[Java]反射
|
2月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
62 9
Java——反射&枚举
|
1月前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
25 2
|
2月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
1月前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
16 0
|
1月前
|
SQL Java 数据库连接
如何在 Java 脚本中有效地使用 JDBC
如何在 Java 脚本中有效地使用 JDBC
16 0
|
2月前
|
Java 程序员 编译器
Java的反射技术reflect
Java的反射技术允许程序在运行时动态加载和操作类,基于字节码文件构建中间语言代码,进而生成机器码在JVM上执行,实现了“一次编译,到处运行”。此技术虽需更多运行时间,但广泛应用于Spring框架的持续集成、动态配置及三大特性(IOC、DI、AOP)中,支持企业级应用的迭代升级和灵活配置管理,适用于集群部署与数据同步场景。
|
3月前
|
SQL Java 关系型数据库
探索Java数据库连接的奥秘:JDBC技术全攻略
探索Java数据库连接的奥秘:JDBC技术全攻略
58 8

热门文章

最新文章