PS:最近简单的学了学后台Servlet+JSP.也就只能学到这里了.没那么多精力去学SSH了,毕竟Android还有很多东西都没学完..

学习内容:

1.如何使用反射+泛型构建通用DAO.

1.使用泛型+反射构建通用DAO.

 DAO的概念曾经写过.其实就是数据访问对象,Date Access Object.其实就是数据库中的数据和Java对象里的一种关联关系的一系列操作.由于以前写过这个概念.就不啰嗦了..简单说一说思想.

 比如说:有两张表 User表和Shop表.

 这是User表中需要进行的操作.

  1. public interface UserDao {
  2. void add(User user);
  3. void delete(User user);
  4. void update(User user);
  5. User select(User user);
  6. }

这是Shop表中需要进行的操作.

  1. public interface ShopDao {
  2. void add(Shop shop);
  3. void delete(Shop shop);
  4. void update(Shop shop);
  5. Shop select(Shop shop);
  6. }

不 难发现,二者都有相同的操作.这样使得代码冗余度较高.那么能否将这两个DAO相同的方法封装成一个呢.这是可以的.这样就构建了一个BaseDao里面 封装了二者相同的操作.当我们需要操作表的时候,我们将T换成User或者是Shop就可以了.当我们实际项目面对的表有非常多的时候,如果都具有相同的 方法.那么就可以这样进行抽取.

  1. public interface BaseDao<T> {
  2. void add(T t);
  3. void delete(T t);
  4. void update(T t);
  5. T select(T t);
  6. }

 这样就构建了一个通用的DAO抽象接口.这里我拿User表来说,如果User表还有其他的业务逻辑呢(比如说查询所有信息等等).那么我们只需要这样.

  1. public interface UserDao extends BaseDao<User> {
  2.  
  3. //按照行查询,额外的业务逻辑.
  4. List<User>findAll();
  5. }

这样我们只需要定义一个新的UserDao就可以了,它继承了BaseDao中的所有方法,当有额外的业务逻辑的时候,只需要添加额外方法就可以了.这样光有接口当然是不行的.我们需要有具体的实现.

 我们先看BaseDao的实现类BaseDaoImp

 我们来看一下思路.

 先上一张原理图.

 1.首先我们如果想对User表进行操作,那么我们首先需要获取User类型.告诉BaseDaoImp,我们当前是需要对User表进行操作.因此构造函数就是用来干这个的.

 2. 当我们获取了User类型之后,如果想要对其进行操作,那么首先需要知道 sql 语句,因此我们需要对sql语句进行拼接.那么拼接过程中,我们需要知道User表内部到底声明了哪些变量.这样就需要使用反射机制.通过反射机制来获取 User实体类中声明的变量,然后对sql进行相关的拼接.那么getsql函数用来完成sql的拼接过程.

 3. 那么拼接完之后还是不行,因为拼接出来的sql语句是这样的:insert into User(id,username,password,email,grade) values(?,?,?,?,?)我们需要对占位符进行赋值操作.那么首先我们需要获取具体的值,那么setArgs就是来获取属性的具体值的.

 4.当获取了具体的值之后,我们就可以通过sql提供给我们的相关函数来执行sql语句了.

 这里函数其实都非常的简单,只要细看,还是能明白其中的道理的.

  1. package com.example.daoimp;
  2.  
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.ParameterizedType;
  5. import java.sql.PreparedStatement;
  6. import java.sql.ResultSet;
  7. import com.example.dao.BaseDao;
  8. import com.example.helper.JdbcDaoHelper;
  9.  
  10. //通用DAO
  11.  
  12. public class BaseDaoImp<T> implements BaseDao<T> {
  13.  
  14. /** 操作常量 */
  15. public static final String SQL_INSERT = "insert";
  16. public static final String SQL_UPDATE = "update";
  17. public static final String SQL_DELETE = "delete";
  18. public static final String SQL_SELECT = "select";
  19.  
  20. private Class<T> EntityClass; // 获取实体类
  21.  
  22. private PreparedStatement statement;
  23.  
  24. private String sql;
  25.  
  26. private Object argType[];
  27.  
  28. private ResultSet rs;
  29.  
  30. @SuppressWarnings("unchecked")
  31. public BaseDaoImp() {
  32.  
  33. /**
  34. * 传递User就是 com.example.daoimp.BaseDaoImp<com.example.bean.User>
  35. * 传递Shop就是 com.example.daoimp.BaseDaoImp<com.example.bean.Shop>
  36. * */
  37. ParameterizedType type = (ParameterizedType) getClass()
  38. .getGenericSuperclass();
  39.  
  40. /**
  41. * 这里如果传递的是User.那么就是class com.example.bean.User
  42. * 如果传递的是Shop. 那么就是class com.example.bean.Shop
  43. * */
  44. EntityClass = (Class<T>) type.getActualTypeArguments()[0];
  45. }
  46.  
  47. @Override
  48. public void add(T t) {
  49. // TODO Auto-generated method stub
  50. sql = this.getSql(SQL_INSERT); //获取sql.
  51. // 赋值.
  52. try {
  53. argType = setArgs(t, SQL_INSERT);
  54. statement = JdbcDaoHelper.getPreparedStatement(sql); //实例化PreparedStatement.
  55. //为sql语句赋值.
  56. statement = JdbcDaoHelper.setPreparedStatementParam(statement,
  57. argType);
  58. statement.executeUpdate(); //执行语句.
  59. } catch (Exception e) {
  60. // TODO Auto-generated catch block
  61. e.printStackTrace();
  62. } finally {
  63. JdbcDaoHelper.release(statement, null); //释放资源.
  64. }
  65. }
  66.  
  67. @Override
  68. public void delete(T t) {
  69. // TODO Auto-generated method stub
  70. sql = this.getSql(SQL_DELETE);
  71. try {
  72. argType = this.setArgs(t, SQL_DELETE);
  73. statement = JdbcDaoHelper.getPreparedStatement(sql);
  74. statement = JdbcDaoHelper.setPreparedStatementParam(statement,
  75. argType);
  76. statement.executeUpdate();
  77. } catch (Exception e) {
  78. // TODO Auto-generated catch block
  79. e.printStackTrace();
  80. } finally {
  81. JdbcDaoHelper.release(statement, null);
  82. }
  83. }
  84.  
  85. @Override
  86. public void update(T t) {
  87. // TODO Auto-generated method stub
  88. sql = this.getSql(SQL_UPDATE);
  89. try {
  90. argType = setArgs(t, SQL_UPDATE);
  91. statement = JdbcDaoHelper.getPreparedStatement(sql);
  92. statement = JdbcDaoHelper.setPreparedStatementParam(statement,
  93. argType);
  94. statement.executeUpdate();
  95. } catch (Exception e) {
  96. // TODO Auto-generated catch block
  97. e.printStackTrace();
  98. } finally {
  99. JdbcDaoHelper.release(statement, null);
  100. }
  101. }
  102.  
  103. @Override
  104. public T select(T t) {
  105. // TODO Auto-generated method stub
  106. sql = this.getSql(SQL_SELECT);
  107. T obj = null;
  108. try {
  109. argType = setArgs(t, SQL_SELECT);
  110. statement = JdbcDaoHelper.getPreparedStatement(sql);
  111. statement = JdbcDaoHelper.setPreparedStatementParam(statement,
  112. argType);
  113. rs = statement.executeQuery();
  114. Field fields[] = EntityClass.getDeclaredFields();
  115. while (rs.next()) {
  116. obj = EntityClass.newInstance();
  117. for (int i = 0; i < fields.length; i++) {
  118. fields[i].setAccessible(true);
  119. fields[i].set(obj, rs.getObject(fields[i].getName()));
  120. }
  121. }
  122. } catch (Exception e) {
  123. // TODO Auto-generated catch block
  124. e.printStackTrace();
  125. }
  126. return obj;
  127.  
  128. }
  129.  
  130. // sql拼接函数 形如 : insert into User(id,username,password,email,grade) values(?,?,?,?,?)
  131. private String getSql(String operator) {
  132.  
  133. StringBuffer sql = new StringBuffer();
  134. // 通过反射获取实体类中的所有变量
  135. Field fields[] = EntityClass.getDeclaredFields();
  136.  
  137. // 插入操作
  138. if (operator.equals(SQL_INSERT)) {
  139. sql.append("insert into " + EntityClass.getSimpleName());
  140. sql.append("(");
  141. for (int i = 0; fields != null && i < fields.length; i++) {
  142. fields[i].setAccessible(true); //这句话必须要有,否则会抛出异常.
  143. String column = fields[i].getName();
  144. sql.append(column).append(",");
  145. }
  146. sql = sql.deleteCharAt(sql.length() - 1);
  147. sql.append(") values (");
  148. for (int i = 0; fields != null && i < fields.length; i++) {
  149. sql.append("?,");
  150. }
  151. sql.deleteCharAt(sql.length() - 1);
  152. // 是否需要添加分号
  153. sql.append(")");
  154. } else if (operator.equals(SQL_UPDATE)) {
  155. sql.append("update " + EntityClass.getSimpleName() + " set ");
  156. for (int i = 0; fields != null && i < fields.length; i++) {
  157. fields[i].setAccessible(true);
  158. String column = fields[i].getName();
  159. if (column.equals("id")) {
  160. continue;
  161. }
  162. sql.append(column).append("=").append("?,");
  163. }
  164. sql.deleteCharAt(sql.length() - 1);
  165. sql.append(" where id=?");
  166. } else if (operator.equals(SQL_DELETE)) {
  167. sql.append("delete from " + EntityClass.getSimpleName()
  168. + " where id=?");
  169. } else if (operator.equals(SQL_SELECT)) {
  170. sql.append("select * from " + EntityClass.getSimpleName()
  171. + " where id=?");
  172. }
  173. return sql.toString();
  174. }
  175.  
  176. // 获取参数.
  177. private Object[] setArgs(T entity, String operator)
  178. throws IllegalArgumentException, IllegalAccessException {
  179.  
  180. Field fields[] = EntityClass.getDeclaredFields();
  181. if (operator.equals(SQL_INSERT)) {
  182.  
  183. Object obj[] = new Object[fields.length];
  184. for (int i = 0; obj != null && i < fields.length; i++) {
  185. fields[i].setAccessible(true);
  186. obj[i] = fields[i].get(entity);
  187. }
  188. return obj;
  189.  
  190. } else if (operator.equals(SQL_UPDATE)) {
  191.  
  192. Object Tempobj[] = new Object[fields.length];
  193. for (int i = 0; Tempobj != null && i < fields.length; i++) {
  194. fields[i].setAccessible(true);
  195. Tempobj[i] = fields[i].get(entity);
  196. }
  197.  
  198. Object obj[] = new Object[fields.length];
  199. System.arraycopy(Tempobj, 1, obj, 0, Tempobj.length - 1);
  200. obj[obj.length - 1] = Tempobj[0];
  201. return obj;
  202.  
  203. } else if (operator.equals(SQL_DELETE)) {
  204.  
  205. Object obj[] = new Object[1];
  206. fields[0].setAccessible(true);
  207. obj[0] = fields[0].get(entity);
  208. return obj;
  209. } else if (operator.equals(SQL_SELECT)) {
  210.  
  211. Object obj[] = new Object[1];
  212. fields[0].setAccessible(true);
  213. obj[0] = fields[0].get(entity);
  214. return obj;
  215. }
  216. return null;
  217. }
  218.  
  219. }

这样就对BaseDao进行了具体的实现.因为我们的User表还有其他额外的操作,那么我们只需要这样.它通过继承BaseDaoImp,然后实现UserDao接口,那么UserDaoImp就即具有了BaseDaoImp的通用方法,还具有了自己其他的额外方法.

  1. package com.example.daoimp;
  2.  
  3. import java.lang.reflect.ParameterizedType;
  4. import java.sql.PreparedStatement;
  5. import java.sql.ResultSet;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8.  
  9. import com.example.bean.User;
  10. import com.example.dao.UserDao;
  11. import com.example.helper.JdbcDaoHelper;
  12.  
  13. public class UserDaoImp extends BaseDaoImp<User> implements UserDao {
  14.  
  15. private Class<?> EntityClass;
  16.  
  17. private String sql;
  18.  
  19. private PreparedStatement statement;
  20.  
  21. private ResultSet rs;
  22.  
  23. private List<User> list;
  24.  
  25. public UserDaoImp() {
  26.  
  27. ParameterizedType type = (ParameterizedType) getClass()
  28. .getGenericSuperclass();
  29. EntityClass = (Class<?>) type.getActualTypeArguments()[0];
  30. }
  31.  
  32. @Override
  33. public List<User> findAll() {
  34. // TODO Auto-generated method stub
  35. StringBuffer b = new StringBuffer();
  36. list = new ArrayList<User>();
  37. sql = b.append("select * from " + EntityClass.getSimpleName())
  38. .toString();
  39. try {
  40. statement = JdbcDaoHelper.getPreparedStatement(sql);
  41. rs = statement.executeQuery();
  42. while (rs.next()) {
  43. User user = new User();
  44. user.setId(rs.getInt("id"));
  45. user.setPassword(rs.getString("password"));
  46. user.setEmail(rs.getString("email"));
  47. user.setUsername(rs.getString("username"));
  48. user.setGrade(rs.getInt("grade"));
  49. list.add(user);
  50. }
  51. } catch (Exception e) {
  52. // TODO Auto-generated catch block
  53. e.printStackTrace();
  54. }
  55. return list;
  56. }
  57.  
  58. }

有 了他们,我们就可以进行具体的操作了,如果还有Shop表,那么同理我们可以去创建一个ShopDao去继承BaseDao,然后在自己的ShopDao 定义其他的额外方法就可以了.当表非常多的时候,我们就可以采用这种思想进行封装.这样写出的代码质量就显得非常的高,耦合度也非常的松散.

 在添加上工具类.

  1. package com.example.helper;
  2.  
  3. import java.sql.Connection;
  4. import java.sql.DriverManager;
  5. import java.sql.PreparedStatement;
  6. import java.sql.ResultSet;
  7. import java.sql.SQLException;
  8.  
  9. public class JdbcDaoHelper {
  10.  
  11. private static final String USER = "root";
  12.  
  13. private static final String PASSWORD = "";
  14.  
  15. private static final String URL = "jdbc:mysql://localhost:3306/usermanager";
  16.  
  17. private static Connection con;
  18.  
  19. // 获取数据库连接对象
  20. public static Connection getConnection() {
  21.  
  22. if (con == null) {
  23. try {
  24. Class.forName("com.mysql.jdbc.Driver");
  25. con = DriverManager.getConnection(URL, USER, PASSWORD);
  26. } catch (ClassNotFoundException e) {
  27. // TODO Auto-generated catch block
  28. e.printStackTrace();
  29. } catch (SQLException e) {
  30. // TODO Auto-generated catch block
  31. e.printStackTrace();
  32. }
  33. } else {
  34. return con;
  35. }
  36. return con;
  37. }
  38.  
  39. public static PreparedStatement getPreparedStatement(String sql)
  40. throws SQLException {
  41.  
  42. return getConnection().prepareStatement(sql);
  43. }
  44.  
  45. public static PreparedStatement setPreparedStatementParam(
  46. PreparedStatement statement, Object obj[]) throws SQLException {
  47.  
  48. for (int i = 0; i < obj.length; i++) {
  49. statement.setObject(i + 1, obj[i]);
  50. }
  51. return statement;
  52. }
  53.  
  54. // 释放资源
  55. public static void release(PreparedStatement ps, ResultSet rs) {
  56. try {
  57. if (con != null) {
  58. con.close();
  59. con = null;
  60. }
  61. if (ps != null) {
  62. ps.close();
  63. ps = null;
  64. }
  65. if (rs != null) {
  66. rs.close();
  67. rs = null;
  68. }
  69. } catch (Exception e) {
  70. // TODO: handle exception
  71. }
  72. }
  73.  
  74. }

最后加上UserBean.

  1. package com.example.bean;
  2.  
  3. public class User {
  4.  
  5. private int id;
  6. private String username;
  7. private String password;
  8. private String email;
  9. private int grade;
  10.  
  11. public User(){
  12.  
  13. }
  14.  
  15. public User(int id,String username,String password,String email,int grade){
  16. this.id = id;
  17. this.username = username;
  18. this.password = password;
  19. this.email = email;
  20. this.grade = grade;
  21. }
  22.  
  23. public int getId() {
  24. return id;
  25. }
  26.  
  27. public void setId(int id) {
  28. this.id = id;
  29. }
  30.  
  31. public String getUsername() {
  32. return username;
  33. }
  34.  
  35. public void setUsername(String username) {
  36. this.username = username;
  37. }
  38.  
  39. public String getPassword() {
  40. return password;
  41. }
  42.  
  43. public void setPassword(String password) {
  44. this.password = password;
  45. }
  46.  
  47. public String getEmail() {
  48. return email;
  49. }
  50.  
  51. public void setEmail(String email) {
  52. this.email = email;
  53. }
  54.  
  55. public int getGrade() {
  56. return grade;
  57. }
  58.  
  59. public void setGrade(int grade) {
  60. this.grade = grade;
  61. }
  62.  
  63. }

测试类.

  1. package com.example.jdbc;
  2.  
  3. import java.util.List;
  4.  
  5. import com.example.bean.User;
  6. import com.example.daoimp.UserDaoImp;
  7.  
  8. public class Main {
  9.  
  10. /**
  11. * @param args
  12. */
  13. public static void main(String[] args) {
  14. // TODO Auto-generated method stub
  15.  
  16. List<User>list = null;
  17. UserDaoImp imp = new UserDaoImp();
  18. list = imp.findAll();
  19. for(User user:list){
  20. System.out.println(user.getId()+" "+user.getUsername()+" "+user.getPassword()+" "+user.getEmail()+" "+user.getGrade());
  21. }
  22. //insert操作.
  23. User user = new User();
  24. user.setId(1);
  25. user.setUsername("代码如风");
  26. user.setPassword("123456");
  27. user.setEmail("123");
  28. user.setGrade(5);
  29. imp.add(user);
  30. //update操作.
  31. User user_1 = new User();
  32. user.setId(1);
  33. user.setUsername("心静如水");
  34. user.setPassword("123456");
  35. user.setEmail("123");
  36. user.setGrade(5);
  37. imp.update(user_1);
  38. }
  39.  
  40. }

 注意(别忘了引入mysql.jar包.)

 最后放上一个源代码:files.cnblogs.com/files/RGogoing/JDBCDao.rar

Java学习笔记之使用反射+泛型构建通用DAO的更多相关文章

  1. Java学习笔记54(反射详解)

    反射概念: java反射机制是在运行状态中,对于任意一个类,都能知道所有属性和方法 对于任意一个对象都能调用它的任意一个方法和属性,这种动态获取和调用的功能称为java的反射机制 实际作用: 已经完成 ...

  2. Java学习笔记--注解和反射

    注解和反射 1. 注解 注解作用: 对程序做出解释 被其他程序读取 注解格式: @注释名,还可以添加一些参数值,例如@SuppressWarnings(value="unchecked&qu ...

  3. Java学习笔记八(反射)

    1.介绍 反射为Java程序在执行时提供了动态的能力.利用反射能够在执行时对程序进行动态的控制.本篇博客着重解说一下Java中的反射. 2.Class类的使用 在Java执行过程中,每一个类被载入后都 ...

  4. Java学习笔记【十、泛型】

    简介 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据 ...

  5. Java学习笔记【一、环境搭建】

    今天把java的学习重新拾起来,一方面是因为公司的项目需要用到大数据方面的东西,需要用java做语言 另一方面是原先使用的C#公司也在慢慢替换为java,为了以后路宽一些吧,技多不压身 此次的学习目标 ...

  6. 20145330第八周《Java学习笔记》

    20145330第八周<Java学习笔记> 第十五章 通用API 通用API 日志:日志对信息安全意义重大,审计.取证.入侵检验等都会用到日志信息 日志API Logger:注意无法使用构 ...

  7. JAVA学习笔记—review基本知识[反射与异常]

    JAVA学习笔记—review基本知识[反射与异常] 1.异常: 1.1异常的分类: Java会将所有的异常封装成对象,其根本父类为Throwable. Throwable有两个子类:Error 和E ...

  8. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  9. Java学习笔记4

    Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...

随机推荐

  1. shell 知识

    解压 tar.bz2文件 bunzip2 linux-2.6.13.tar.bz2 | tar xvf -

  2. git 撤销提交的文件

    一.问题 近期在使用git时遇到一个问题,就是在git上传文件时,将一个100兆的大文件添加到了git,并执行了push操作,这时在上传完毕后,会提示这个错误 Large files detected ...

  3. openSUSE 11 上的配置可以Xmanager远程桌面

    openSUSE 11 上的配置(适用于默认图形环境为KDE的Linux): 1.配置KDM. openSUSE 11的默认图形环境为KDE,虽然可以同时安装GDM和KDM,但默认只启动了KDM.所以 ...

  4. Android Studio 1.0.1 + Genymotion安卓模拟器打造高效安卓开发环境

    我们开发安卓大多是使用Eclipse和安卓SDK中自带的安卓模拟器.当然,Google早就推出了自己的安卓开发环境——Android studio,在不久前,Google发布了Android Stud ...

  5. 【转】优化Web程序的最佳实践

    自动排版有点乱,看着蛋疼,建议下载中文PDF版阅读或阅读英文原文. Yahoo!的Exceptional Performance团队为改善Web性能带来最佳实践.他们为此进行了 一系列的实验.开发了各 ...

  6. 网络异步编程(C#)团购课

    新生命开发团队大石头讲解网络异步编程(C#) 内容:网络编程基础.IOCP.APM.SAEA 时长:2~3小时 价格:20元,20人及以上成团,http://item.taobao.com/item. ...

  7. ssc

    接了一个ssc的小项目,却因为对方的不作答而半途而废.我写了一天的代码算是废了. 主程序 <?xml version="1.0" encoding="utf-8&q ...

  8. 我心中的核心组件(可插拔的AOP)~第四回 异常拦截器

    回到目录 之前说过有关拦截器的文章,第二回  缓存拦截器,事实上,在那讲里说的最多是AOP和缓存组件,对于拦截的概念并没有详细的说明,这一讲,不说AOP,主要说一下拦截器,拦截器Interceptio ...

  9. Fedora Static Configure

    Background Currenlty! I am work on fedora system, but the static-ip has required, but the fedora hav ...

  10. iOS-----用LLDB调试,让移动开发更简单(二)

    image lookup –address 当我们有一个地址,想查找这个地址具体对应的文件位置,可以使用image lookup --address,简写为image lookup -a e.g: 当 ...