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;
- }
- }
Java反射结合JDBC写的一个通用DAO的更多相关文章
- 为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式
为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式,代码如下: public class DataComparer<T>:IEqualityCompare ...
- 闲来无事,用Java的软引用写了一个山寨的缓存
闲来无事,用Java的软引用写了一个山寨的缓存 博客分类: java基础 众所周知java中的引用分为 StrongReference.SoftReference.WeakReference.Phan ...
- JDBC课程5--利用反射及JDBC元数据(ResultSetMetaData)编写通用的查询方法
/**-利用反射及JDBC元数据编写通用的查询方法 * 1.先利用SQl语句进行查询,得到结果集--> * 2.查找到结果集的别名:id--> * 3.利用反射创建实体类的对象,创建aut ...
- 【java基础】随手写的一个日期计算,新手可以看看
随手写的一个例子, 只是练习下自己的代码布局以及思路.. 1. 先写下简单的测试 2. 根据常用的不用修改的变量抽取出来, 作为常量(常量的命名可能有点不规范,谅解~) 3. 方法的作用不一样, 抽取 ...
- java环境搭建和写出一个Helloworld
一.安装环境和配置环境变量(必要环节) 安装java并配置环境变量 :在"系统变量"中设置3项属性,JAVA_HOME,PATH,CLASSPATH(大小写无所谓),若已存在则点击 ...
- 使用ResultSet,写了一个通用的查询方法
此方法很烂,以后优化 /** * 通用的查询方法:SELECT */ @SuppressWarnings({ "unchecked", "rawtypes" } ...
- 利用反射和JDBC元数据实现更加通用的查询方法
package com.at221.jdbc; import java.io.IOException; import java.io.InputStream; import java.sql.*; i ...
- <五>JDBC_利用反射及JDBC元数据编写通用的查询方法
此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...:通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山! 一.使用JDBC驱动 ...
- JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法
JDBC元数据 1)DatabaseMetaData /** * 了解即可:DatabaseMetaData是描述数据库的元数据对象 * 可以由Connection得到 */ 具体的应用代码: @Te ...
随机推荐
- STL源码剖析之list的sort函数实现
SGI STL的list的函数的实现源码大致如下: //list 不能使用sort函数,因为list的迭代器是bidirectional_iterator, 而sort //sort函数要求rand ...
- Oracle学习.Windows 命令行 启动ORACLE服务与实例
使用数据库前要先打开数据库的实例和监听器! --总结启动命令如下: lsnrctl [start|stop|status] --启动监听器,停止监听器,查看监听器的 ...
- Linux的文件属性
在Linux中,文件的拥有者可以将文件的属性设置成三种属性,可读(r).可写(w)和可执行(x).文件又分为三个不同的用户级别,文件的拥有者(u),文件的所属组(g),其他用户(o). 第一个字符显示 ...
- 遇到java.lang.OutOfMemoryError: Java heap space问题【持续跟踪中...】
昨天下午app服务端无缘无故又502错了,我打开tomcat 日志: INFO: org.tuckey.web.filters.urlrewrite.UrlRewriteFilter DEBUG: i ...
- trace openjdk from systemtap
here are several different tactics to trace openjdk from systemtap. The first relies on sys/sdt.h dt ...
- [转] Tomcat 配置 SSL
PS: keystore有自己的访问密码,这个保护层次要低一些,然后keystore里面存有自己的私钥,所以用户要破解的话,既要有keystore,又要有keystore的密码,p12是客户端keys ...
- ubuntu常用文件搜索命令 分类: linux 学习笔记 ubuntu 2015-07-05 15:40 84人阅读 评论(0) 收藏
1.find find [搜索路径] [搜索关键字] 比如查找/test中文件名为t5.tmp的文件: 查找根目录下大于100M的文件 注意,这里的204800单位是块,1块=512字节 在根目录下查 ...
- 处理json中影响解析的多余引号
在xml中,敏感字符是尖括号,在json中,敏感字符是引号,上文中我们介绍了如何处理xml中的敏感字符,本文说说如何处理json中的敏感字符. 思路与上文相同,不再赘述.直接上代码: json–> ...
- Android(java)学习笔记183:判断SD卡状态和存储空间大小
当我们在使用SD卡时候,如果我们想往SD卡里读写数据,我们必须在这之前进行一个逻辑判断,那就是判断SD卡状态和SD存储空间大小: 核心代码: String status = Environment.g ...
- iOS UIKit:Navigation Controllers
navigation controller是一种层次结构的container view controller,即其通过一个view controllers栈来管理内部的content view con ...