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

大家除学JDBC时,也会有这种感触,一般写的DAO只能用在一张表上,不能通用,如果你的程序有多张表,就需要写多个DAO,或者使用一些复杂设计来达到这个目的。而这个反射方式实现的DAO,就不需要很复杂的设计,就可以实现DAO的通用。

这个通用是有前提的,就是DAO接受的参数必须是绝对符合JavaBean标准的对象。而且JavaBean的属性类型,必须跟数据库中表的数据类型保持一致。否则就会出问题,下面贴出代码,写得不好,别见怪

  1. package com.sldll.cms.dao;
  2.  
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.InvocationTargetException;
  5. import java.lang.reflect.Method;
  6. import java.sql.PreparedStatement;
  7. import java.sql.ResultSet;
  8. import java.sql.SQLException;
  9. import java.sql.Statement;
  10. import java.util.ArrayList;
  11. import java.util.HashMap;
  12. import java.util.Iterator;
  13. import java.util.List;
  14. import java.util.Map;
  15.  
  16. //0oO
  17. public class GeneralDAO {
  18.  
  19. //---------------------------------查询部分--------------------------------------------------------------------------
  20. /**
  21. * 查询所有记录
  22. * @param obj 表对应的JavaBean对象
  23. * @return 所有记录构成的list
  24. * @throws Exception
  25. */
  26. public List<Object> findAll(Object obj) throws Exception {
  27.  
  28. List<Object> list = new ArrayList<Object>();
  29. ResultSet rs = null;
  30. try {
  31.  
  32. // 获取数据库连接
  33. Statement stmt = DBConnectionManager.getConnection()
  34. .createStatement();
  35. // 构建sql语句
  36. String tableName = obj.getClass().getName();
  37. tableName = tableName.substring(tableName.lastIndexOf(".") + 1);
  38. String sql = "select * from " + tableName;
  39.  
  40. // 执行sql语句
  41. rs = stmt.executeQuery(sql);
  42.  
  43. while (rs.next()) {
  44. list.add(createObj(rs, obj));
  45. }
  46. } catch (Exception e) {
  47. // TODO Auto-generated catch block
  48. e.printStackTrace();
  49. throw e;
  50. } finally {
  51. // 关闭连接
  52. if (rs != null) {
  53. rs.close();
  54. }
  55. DBConnectionManager.closeConnection();
  56. }
  57.  
  58. return list;
  59. }
  60.  
  61. /**
  62. * 对指定的表执行指定的sql查询语句
  63. * @param obj
  64. * 以该表对应的JavaBean对象决定表
  65. * @param query
  66. * 要对该表执行的sql语句
  67. * @return
  68. * @throws Exception
  69. */
  70. public List<Object> findByNameQuery(Object obj, String query) throws Exception {
  71. // TODO Auto-generated method stub
  72. List<Object> list = null;
  73. try {
  74. Statement sql_statement = DBConnectionManager.getConnection()
  75. .createStatement();
  76. //执行传递的sql语句
  77. ResultSet rs = sql_statement.executeQuery(query);
  78. list = new ArrayList<Object>();
  79. if (rs != null) {
  80. while (rs.next()) {
  81. list.add(createObj(rs, obj));
  82. }
  83. }
  84. return list;
  85. } catch (Exception e) {
  86. // TODO Auto-generated catch block
  87. e.printStackTrace();
  88. throw e;
  89. } finally {
  90. DBConnectionManager.closeConnection();
  91. }
  92.  
  93. }
  94.  
  95. /**
  96. * 按条件对指定表进行查询
  97. * @param obj
  98. * 以该表对应的JavaBean对象决定表
  99. * @param condition
  100. * 查询的条件,key:条件 value:值
  101. * @param isFuzzzy
  102. * 是否支持模糊查询
  103. * @return
  104. * @throws Exception
  105. */
  106. public List<Object> findByNameQuery(Object obj, Map<Object,Object> condition,boolean isFuzzy) throws Exception {
  107. List<Object> list = new ArrayList<Object>();
  108. try {
  109.  
  110. String tablename = getTableName(obj);
  111. StringBuilder sb = new StringBuilder("select * from " + tablename);
  112. PreparedStatement state = null;
  113. if(isFuzzy){
  114. addFuzzyConditionString(sb, condition);
  115. }
  116. else{
  117. addConditionString(sb, condition);
  118. }
  119. state = DBConnectionManager.getConnection().prepareStatement(sb.toString());
  120. state = setSqlValue(state, condition,isFuzzy);
  121. ResultSet rs = state.executeQuery();
  122. if (rs != null) {
  123. while (rs.next()) {
  124. list.add(createObj(rs, obj));
  125. }
  126. }
  127. return list;
  128. } catch (Exception e) {
  129. // TODO Auto-generated catch block
  130. e.printStackTrace();
  131. throw e;
  132. } finally {
  133. DBConnectionManager.closeConnection();
  134. }
  135. }
  136.  
  137. //-------------------------------------创建部分--------------------------------------------------------------------------
  138. /**
  139. * 在数据库里新建一条记录
  140. * @param obj
  141. * 描述记录的对象,必须是数据库中某张表对应的JavaBean对象
  142. * @return
  143. * 新建成功返回真,否则返回假
  144. * @throws Exception
  145. */
  146. public boolean create(Object obj) throws Exception{
  147. // 获取数据库连接
  148. try {
  149. // 构建sql语句
  150. Map<Object, Object> map = getObjectFieldValue(obj);
  151. String tableName = obj.getClass().getName();
  152. tableName = tableName.substring(tableName.lastIndexOf(".") + 1);
  153. StringBuilder sb = new StringBuilder("insert into " + tableName);
  154. addCreateString(sb, map);
  155. PreparedStatement stmt = DBConnectionManager.getConnection()
  156. .prepareStatement(sb.toString());
  157. setSqlValue(stmt, map,false);
  158. int count = stmt.executeUpdate();
  159. if(count>0){
  160. return true;
  161. }
  162. else{
  163. return false;
  164. }
  165. } catch (Exception e) {
  166. e.printStackTrace();
  167. throw e;
  168. } finally {
  169. DBConnectionManager.closeConnection();
  170. }
  171. }
  172.  
  173. //-------------------------------------删除部分----------------------------------------------------------------------------
  174. /**
  175. * 删除表中所有记录
  176. * @param obj
  177. * JavaBean对象,决定要删除的是哪张表
  178. * @return
  179. * 删除成功返回真,否则返回假
  180. */
  181. public boolean deleteAll(Object obj) throws Exception{
  182. String delete_sql = "delete from "+getTableName(obj);
  183. PreparedStatement pstmt;
  184. try {
  185. pstmt = DBConnectionManager.getConnection().prepareStatement(delete_sql);
  186. int count = pstmt.executeUpdate();
  187. if(count>0){
  188. return true;
  189. }
  190. else{
  191. return false;
  192. }
  193. } catch (Exception e) {
  194. // TODO Auto-generated catch block
  195. e.printStackTrace();
  196. throw e;
  197. }
  198. finally{
  199. DBConnectionManager.closeConnection();
  200. }
  201.  
  202. }
  203.  
  204. /**
  205. * 在指定表中删除给定ID的记录
  206. * @param obj
  207. * 表示要删除的表
  208. * @param condition
  209. * 删除的条件 key:字段(一般为字符串) value:值
  210. * @return
  211. */
  212. public boolean delete(Object obj,Map<Object,Object> condition) throws Exception{
  213. //构建sql语句
  214. StringBuilder sb = new StringBuilder("delete from "+getTableName(obj));
  215. addConditionString(sb, condition);
  216. try {
  217. PreparedStatement pstmt = DBConnectionManager.getConnection().prepareStatement(sb.toString());
  218. setSqlValue(pstmt, condition,false);
  219. int count = pstmt.executeUpdate();
  220. if(count > 0){
  221. return true;
  222. }
  223. else{
  224. return false;
  225. }
  226. } catch (Exception e) {
  227. // TODO Auto-generated catch block
  228. e.printStackTrace();
  229. throw e;
  230. }
  231. finally{
  232. DBConnectionManager.closeConnection();
  233. }
  234. }
  235.  
  236. //-------------------------------------更新部分----------------------------------------------------------------------------
  237. /**
  238. * 更新指定表的记录
  239. * @param obj
  240. * 用来确定表的Java对象
  241. * @param map
  242. * 要设置的字段值,key:字段(字符串),value:值
  243. * @param condition
  244. * 筛选条件
  245. * @return
  246. */
  247. public boolean update(Object obj,Map<Object,Object> map,Map<Object, Object>condition) throws Exception {
  248. StringBuilder sb = new StringBuilder("update "+getTableName(obj));
  249. addSetString(sb,map);
  250. addConditionString(sb, condition);
  251. try {
  252. PreparedStatement pstmt = DBConnectionManager.getConnection().prepareStatement(sb.toString());
  253. List<Object> values = new ArrayList<Object>();
  254. getValuesToList(values,map);
  255. getValuesToList(values, condition);
  256. setSqlValue(pstmt, values);
  257.  
  258. int count = pstmt.executeUpdate();
  259. if(count > 0){
  260. return true;
  261. }
  262. else{
  263. return false;
  264. }
  265. } catch ( Exception e) {
  266. // TODO Auto-generated catch block
  267. e.printStackTrace();
  268. throw e;
  269. }
  270. finally{
  271. DBConnectionManager.closeConnection();
  272. }
  273. }
  274.  
  275. private List<Object> getValuesToList(List<Object> values,Map<Object, Object> map) {
  276.  
  277. for (Iterator<Object> it = map.keySet().iterator(); it.hasNext();) {
  278. Object value = map.get(it.next());
  279. values.add(value);
  280. }
  281. return values;
  282. }
  283.  
  284. /**
  285. * 获取JavaBean对象的字段值放到容器中
  286. * @param obj
  287. * JavaBean对象
  288. * @return
  289. * @throws IllegalAccessException
  290. * @throws InvocationTargetException
  291. */
  292. private Map<Object, Object> getObjectFieldValue(Object obj)
  293. throws IllegalAccessException, InvocationTargetException {
  294. Map<Object, Object> map = new HashMap<Object,Object>();
  295.  
  296. Field fields[] = obj.getClass().getFields();
  297. Method methods[] = obj.getClass().getMethods();
  298.  
  299. // 给字段设置值
  300. for (int i = 0; i < fields.length; i++) {
  301. // 用字段的名字构建set方法的名字
  302. String fieldName = fields[i].getName();
  303.  
  304. String methodName = "get" + fieldName.substring(0, 1).toUpperCase()
  305. + fieldName.substring(1);
  306.  
  307. // 查找对应的方法
  308. Method method = null;
  309. for (int j = 0; j < methods.length; j++) {
  310. if (methods[j].getName().equals(methodName)) {
  311. method = methods[j];
  312. break;
  313. }
  314. }
  315. // 如果存在这个方法
  316. if (method != null) {
  317. // 开始执行方法,获取当前的JavaBean对象字段值
  318. Object value = method.invoke(obj, new Object[] { });
  319. map.put(fieldName, value);
  320. }
  321. }
  322. return map;
  323. }
  324.  
  325. private void addSetString(StringBuilder sb, Map<Object, Object> map) {
  326. // TODO Auto-generated method stub
  327. if (!map.isEmpty()) {
  328. sb.append(" set ");
  329. for (Iterator<Object> it = map.keySet().iterator(); it.hasNext();) {
  330. String key = (String) it.next();
  331. if (null == key) {
  332. continue;
  333. }
  334. sb.append(key+"=?,");
  335. }
  336. sb.deleteCharAt(sb.lastIndexOf(","));
  337. System.out.println(sb.toString());
  338. }
  339. }
  340.  
  341. /**
  342. * 在现有sql创建语句后面追加字段名和占位符
  343. * @param sb
  344. * @param map
  345. */
  346. private void addCreateString(StringBuilder sb,Map<Object, Object> map) {
  347. // TODO Auto-generated method stub
  348. sb.append("(");
  349. int count = 0;
  350. for (Iterator<Object> it = map.keySet().iterator(); it.hasNext();) {
  351. String key = (String) it.next();
  352. if (null == key) {
  353. continue;
  354. }
  355. sb.append(key + ",");
  356. count++;
  357. }
  358. sb.deleteCharAt(sb.lastIndexOf(","));
  359. sb.append(") values(");
  360. for (int i = 0; i < count; i++) {
  361. sb.append("?,");
  362. }
  363. sb.deleteCharAt(sb.lastIndexOf(","));
  364. sb.append(")");
  365. System.out.println(sb.toString());
  366. }
  367.  
  368. /**
  369. * 在现有sql查询语句后面追加判断条件
  370. * @param sb where之前的sql
  371. * @param condition 条件(key:字段名;value:值)
  372. * @return 使用占位符的sql语句
  373. */
  374. private String addConditionString(StringBuilder sb, Map<Object,Object> condition) {
  375. if (!condition.isEmpty()) {
  376. sb.append(" where ");
  377. int i = 0;
  378.  
  379. for (Iterator<Object> it = condition.keySet().iterator(); it.hasNext();) {
  380. String key = (String) it.next();
  381. if (null == key) {
  382. continue;
  383. }
  384. if (i != 0) {
  385. sb.append(" and ");
  386. }
  387. if (key.indexOf("<") != -1 || key.indexOf(">") != -1
  388. || key.indexOf("=") != -1) {
  389. sb.append(key + "?");
  390. } else {
  391. sb.append(key + "=" + "?");
  392. }
  393.  
  394. i++;
  395.  
  396. }
  397.  
  398. }
  399. System.out.println(sb.toString());
  400. return sb.toString();
  401. }
  402.  
  403. private String addFuzzyConditionString(StringBuilder sb,Map<Object,Object>condition) {
  404. if (!condition.isEmpty()) {
  405. sb.append(" where ");
  406. int i = 0;
  407.  
  408. for (Iterator<Object> it = condition.keySet().iterator(); it.hasNext();) {
  409. String key = (String) it.next();
  410. if (null == key) {
  411. continue;
  412. }
  413. if (i != 0) {
  414. sb.append(" or ");
  415. }
  416. sb.append(key + " like " +"?");
  417. i++;
  418. }
  419.  
  420. }
  421. System.out.println(sb.toString());
  422. return sb.toString();
  423. }
  424.  
  425. /**
  426. * 设置现有sql语句的占位符的值
  427. * @param state
  428. * @param map
  429. * @return
  430. * @throws SQLException
  431. */
  432. private PreparedStatement setSqlValue(PreparedStatement state, Map<Object,Object> map,boolean isFuzzy)
  433. throws SQLException {
  434. if (!map.isEmpty()) {
  435. int i = 1;
  436. for (Iterator<Object> it = map.keySet().iterator(); it.hasNext();) {
  437. Object value = map.get(it.next());
  438. if(isFuzzy){
  439. state.setObject(i++, "%"+value+"%");
  440. }else{
  441. state.setObject(i++, value);
  442. }
  443. }
  444.  
  445. }
  446. return state;
  447. }
  448. private PreparedStatement setSqlValue(PreparedStatement state, List<Object> values)
  449. throws SQLException {
  450. if (!values.isEmpty()) {
  451. int i = 1;
  452. for (Iterator<Object> it = values.iterator(); it.hasNext();) {
  453. Object value = it.next();
  454. state.setObject(i++, value);
  455. }
  456.  
  457. }
  458. return state;
  459. }
  460.  
  461. private String getTableName(Object obj) {
  462. String tablename = obj.getClass().getName();
  463. tablename = tablename.substring(tablename.lastIndexOf(".") + 1);
  464. return tablename;
  465. }
  466. // 利用反射构建对象
  467.  
  468. private Object createObj(ResultSet rs, Object obj)
  469. throws Exception {
  470. // TODO Auto-generated method stub
  471. Object object = obj.getClass().newInstance();
  472. // 获取字段
  473. Field fields[] = obj.getClass().getFields();
  474. // 获取方法
  475. Method methods[] = obj.getClass().getMethods();
  476.  
  477. // 给字段设置值
  478. for (int i = 0; i < fields.length; i++) {
  479. // 用字段的名字构建set方法的名字
  480. String fieldName = fields[i].getName();
  481. String methodName = "set" + fieldName.substring(0, 1).toUpperCase()
  482. + fieldName.substring(1);
  483.  
  484. // 查找对应的方法
  485. Method method = null;
  486. for (int j = 0; j < methods.length; j++) {
  487. if (methods[j].getName().equals(methodName)) {
  488. method = methods[j];
  489. break;
  490. }
  491. }
  492.  
  493. // 如果存在这个方法
  494. if (method != null) {
  495. // 开始执行方法,为当前的JavaBean对象字段设置值
  496. Object value = rs.getObject(fieldName);
  497. method.invoke(object, new Object[] { value });
  498.  
  499. }
  500. }
  501. return object;
  502. }
  503.  
  504. }

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. STL源码剖析之list的sort函数实现

    SGI  STL的list的函数的实现源码大致如下: //list 不能使用sort函数,因为list的迭代器是bidirectional_iterator, 而sort //sort函数要求rand ...

  2. Oracle学习.Windows 命令行 启动ORACLE服务与实例

    使用数据库前要先打开数据库的实例和监听器! --总结启动命令如下: lsnrctl  [start|stop|status]                  --启动监听器,停止监听器,查看监听器的 ...

  3. Linux的文件属性

    在Linux中,文件的拥有者可以将文件的属性设置成三种属性,可读(r).可写(w)和可执行(x).文件又分为三个不同的用户级别,文件的拥有者(u),文件的所属组(g),其他用户(o). 第一个字符显示 ...

  4. 遇到java.lang.OutOfMemoryError: Java heap space问题【持续跟踪中...】

    昨天下午app服务端无缘无故又502错了,我打开tomcat 日志: INFO: org.tuckey.web.filters.urlrewrite.UrlRewriteFilter DEBUG: i ...

  5. trace openjdk from systemtap

    here are several different tactics to trace openjdk from systemtap. The first relies on sys/sdt.h dt ...

  6. [转] Tomcat 配置 SSL

    PS: keystore有自己的访问密码,这个保护层次要低一些,然后keystore里面存有自己的私钥,所以用户要破解的话,既要有keystore,又要有keystore的密码,p12是客户端keys ...

  7. ubuntu常用文件搜索命令 分类: linux 学习笔记 ubuntu 2015-07-05 15:40 84人阅读 评论(0) 收藏

    1.find find [搜索路径] [搜索关键字] 比如查找/test中文件名为t5.tmp的文件: 查找根目录下大于100M的文件 注意,这里的204800单位是块,1块=512字节 在根目录下查 ...

  8. 处理json中影响解析的多余引号

    在xml中,敏感字符是尖括号,在json中,敏感字符是引号,上文中我们介绍了如何处理xml中的敏感字符,本文说说如何处理json中的敏感字符. 思路与上文相同,不再赘述.直接上代码: json–> ...

  9. Android(java)学习笔记183:判断SD卡状态和存储空间大小

    当我们在使用SD卡时候,如果我们想往SD卡里读写数据,我们必须在这之前进行一个逻辑判断,那就是判断SD卡状态和SD存储空间大小: 核心代码: String status = Environment.g ...

  10. iOS UIKit:Navigation Controllers

    navigation controller是一种层次结构的container view controller,即其通过一个view controllers栈来管理内部的content view con ...