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

Java反射结合JDBC写的一个通用DAO的更多相关文章

  1. 为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式

    为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式,代码如下: public class DataComparer<T>:IEqualityCompare ...

  2. 闲来无事,用Java的软引用写了一个山寨的缓存

    闲来无事,用Java的软引用写了一个山寨的缓存 博客分类: java基础 众所周知java中的引用分为 StrongReference.SoftReference.WeakReference.Phan ...

  3. JDBC课程5--利用反射及JDBC元数据(ResultSetMetaData)编写通用的查询方法

    /**-利用反射及JDBC元数据编写通用的查询方法 * 1.先利用SQl语句进行查询,得到结果集--> * 2.查找到结果集的别名:id--> * 3.利用反射创建实体类的对象,创建aut ...

  4. 【java基础】随手写的一个日期计算,新手可以看看

    随手写的一个例子, 只是练习下自己的代码布局以及思路.. 1. 先写下简单的测试 2. 根据常用的不用修改的变量抽取出来, 作为常量(常量的命名可能有点不规范,谅解~) 3. 方法的作用不一样, 抽取 ...

  5. java环境搭建和写出一个Helloworld

    一.安装环境和配置环境变量(必要环节) 安装java并配置环境变量 :在"系统变量"中设置3项属性,JAVA_HOME,PATH,CLASSPATH(大小写无所谓),若已存在则点击 ...

  6. 使用ResultSet,写了一个通用的查询方法

    此方法很烂,以后优化 /** * 通用的查询方法:SELECT */ @SuppressWarnings({ "unchecked", "rawtypes" } ...

  7. 利用反射和JDBC元数据实现更加通用的查询方法

    package com.at221.jdbc; import java.io.IOException; import java.io.InputStream; import java.sql.*; i ...

  8. <五>JDBC_利用反射及JDBC元数据编写通用的查询方法

    此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...:通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山! 一.使用JDBC驱动 ...

  9. JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法

    JDBC元数据 1)DatabaseMetaData /** * 了解即可:DatabaseMetaData是描述数据库的元数据对象 * 可以由Connection得到 */ 具体的应用代码: @Te ...

随机推荐

  1. hdoj 2036 改革春风吹满地

    改革春风吹满地 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  2. Struct2 拦截器

    拦截器的整个过程 程序是在执行Action之前调用的拦截器,整个过程是这样子的 这里面注意两个问题: public void serviceAction(HttpServletRequest requ ...

  3. SQLServer加入域后无法远程连接

    如果您更改的SQLServer的远程连接端口(默认1433),加入域后,防火墙会把自定义规则都禁用掉 所以,你得进防火墙,查看,是否防火墙关闭了,我的就是关闭了,找了半天原因

  4. ListView 选择多项目返回的之前的那项

      当ListView多选时返回第一次选中的项索引 正确 定义一个变量 =-1 表示第一次没选任何一项   private int FirstSelectedIndex =-1;     更新Firs ...

  5. 使用java进行文件编码转换

    在开发过程中,可能会遇到文件编码的转换,尽管说开发工具eclipse能够转换编码,可是有的情况却非常不方便.比方,原来文件本身的编码是GBK,如今要转换成UTF-8,假设直接在eclipse中把文件编 ...

  6. Android的配置界面PreferenceActivity

    我想大家对于android的系统配置界面应该不会陌生吧,即便陌生,那么下面的界面应该似曾相识吧,假若还是不认识,那么也没有关系,我们这一节主要就是介绍并讲解android 中系统配置界面的使用,相信大 ...

  7. j2ee学习笔记URLEncoder.encode(String , enc)处理特殊字符

    从页面上传递数据时,特殊字符对于超链接会自动进行解码 : 其他方式需要手动进行解码.

  8. Android(java)学习笔记189:eclipse 导入项目是提示:某些项目因位于工作空间目录中而被隐藏。

    导致这个错误的原因是工程重名了: 并不是仅仅指文件夹重名,相信很多人也曾经修改过文件夹的名称,可惜没什么用处,关键是修改工程里面的一个文件!也就是.project这个文件! 用记事本打开,修改一下&l ...

  9. sendkeys && appactivate

    sendkeys    用于输入键盘按键 appactivate 用于聚焦程序 on error resume next set ws = createObject("wscript.she ...

  10. SCIP读书笔记(1)

    这书也算是必修吧,尤其是我这种非科班人员,还是应该抽时间尽量学习一下.大致翻过一遍,习题非常多,尽力吧. ##构造过程抽象 * 为了表述认知,每种语言都提供了三种机制:基本元素:组合方式:抽象方法. ...