首先解释一下为什么要学习泛型DAO。平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写很多的操作数据库的方法。当我们有很多的javaben的时候我们会写很多的接口和实现类,并且里面的代码都是相同的,这样太麻烦,我们就不能写一个类,在类里面传入泛型,让类根据泛型,创建出一个实例对象,这样就出现了泛型DAO。

一、需要提前准备的知识如下

反射关键的类:

Class<T>类 是java.lang包下,Class类的实例表示正在运行的 Java 应用中的类和接口。

Type接口 是java.lang.reflect包下的是Java类型的通用超级接口。这些包括原始类型,参数化类型,数组类型和类型变量

ParameterizedType接口 是java.lang.reflect包下是Type的子接口,表示一个参数化类型,如Collection<String>

Field类 是java.lang.reflect包下,提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实体字段

AccessibleObject类 是java.lang.reflect包下,是Filed、Method和Constructor对象的基类。提供了将反射的对象标记为在使用时取消默认 Java语言访问控制检查的能力

反射关键的方法:

ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();

//getGenericSuperclass() 返回此Class 所有的实体(类、接口、基本类型或者void)的直接超类的 Type

Class<T> entityClass = (Class<T>) type.getActualTypeArguments()[0];

//getActualTypeArguments()  返回此类型的实际类型参数的数组Type对象

getDeclaredFields() 返回 Field 对象的一个数组,这些对象所表示的类或接口所声明的所有字段。(公共、保护、默认、私有字段,不包括继承的字段)

newInstance() 创建此 Class 对象的新实例

setAccessible(boolean flag) 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则实施访问检查

二、下面是泛型DAO的源码

User实体类:主要声明一个实体,get、set方法来获取实体的属性

  1. package zhr.bean;
  2.  
  3. public class User {
  4. private int id;
  5. private String username;
  6. private String password;
  7.  
  8. public int getId() {
  9. return id;
  10. }
  11.  
  12. public void setId(int id) {
  13. this.id = id;
  14. }
  15.  
  16. public String getUsername() {
  17. return username;
  18. }
  19.  
  20. public void setUsername(String username) {
  21. this.username = username;
  22. }
  23.  
  24. public String getPassword() {
  25. return password;
  26. }
  27.  
  28. public void setPassword(String password) {
  29. this.password = password;
  30. }
  31.  
  32. @Override
  33. public String toString() {
  34. return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
  35. }
  36.  
  37. }

BaseDao接口:用来写泛型DAO的核心接口主要就是一些增删改查的方法

  1. package zhr.dao;
  2.  
  3. public interface BaseDao<T> {
  4. T selectByID(int id);
  5.  
  6. T select(T t);
  7.  
  8. void add(T t);
  9.  
  10. void update(T t);
  11.  
  12. void delete(T t);
  13. }

UserDao接口:主要DAO接口,类似的DAO接口也可以写这样只需要继承BaseDao接口就可以,提高了代码的复用性,也可以自己定义功能方法

  1. package zhr.dao;
  2.  
  3. import java.util.List;
  4.  
  5. import zhr.bean.User;
  6.  
  7. public interface UserDao extends BaseDao<User> {
  8. List<User> findAll();
  9. }

BaseDaoImpl实现类:实现BaseDao接口,构造方法使用了反射获取实体类,这是泛型DAO核心实现类,需要详细写,增删改查,或者更多功能,比如通过id来查询,或者给两个参数查询between and,大于或者小于 核心思想就是反射。

  1. 1 package zhr.daoimpl;
  2. 2
  3. 3 import java.lang.reflect.Field;
  4. 4 import java.lang.reflect.ParameterizedType;
  5. 5 import java.sql.Connection;
  6. 6 import java.sql.PreparedStatement;
  7. 7 import java.sql.ResultSet;
  8. 8 import java.sql.SQLException;
  9. 9
  10. 10 import util.ConnectionManager;
  11. 11 import zhr.dao.BaseDao;
  12. 12
  13. 13 public class BaseDaoImpl<T> implements BaseDao<T> {
  14. 14
  15. 15 private Connection conn;
  16. 16 private PreparedStatement ps;
  17. 17 private ResultSet rs;
  18. 18 private Class<T> EntityClass;// 获取实体类
  19. 19
  20. 20 @SuppressWarnings("unchecked")
  21. 21 public BaseDaoImpl() {
  22. 22 /**
  23. 23 * 传递User就是 zhr.daoimpl.BaseDaoImpl<zhr.bean.User> 传递Shop就是
  24. 24 * zhr.daoimpl.BaseDaoImpl<zhr.bean.Shop>
  25. 25 */
  26. 26 ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
  27. 27 System.out.println(type);
  28. 28 /**
  29. 29 * 这里如果传递的是User.那么就是zhr.bean.User 如果传递的是Shop. 那么就是zhr.bean.Shop
  30. 30 *
  31. 31 */
  32. 32
  33. 33 EntityClass = (Class<T>) type.getActualTypeArguments()[0];
  34. 34 System.out.println(EntityClass);
  35. 35 }
  36. 36
  37. 37 @Override
  38. 38 public T selectByID(int id) {
  39. 39 StringBuffer sqlb = new StringBuffer();
  40. 40 // 通过反射获取实体类中的所有变量
  41. 41 Field fields[] = EntityClass.getDeclaredFields();
  42. 42 sqlb.append("select * from " + EntityClass.getSimpleName() + " where id=?");
  43. 43 T obj = null;
  44. 44 try {
  45. 45 conn = ConnectionManager.getConnection();
  46. 46 ps = conn.prepareStatement(sqlb.toString());
  47. 47 ps.setInt(1, id);
  48. 48 rs = ps.executeQuery();
  49. 49 fields = EntityClass.getDeclaredFields();
  50. 50 while (rs.next()) {
  51. 51 obj = EntityClass.newInstance();
  52. 52 for (int i = 0; i < fields.length; i++) {
  53. 53 fields[i].setAccessible(true);
  54. 54 fields[i].set(obj, rs.getObject(fields[i].getName()));
  55. 55 }
  56. 56 }
  57. 57
  58. 58 } catch (SQLException e) {
  59. 59 e.printStackTrace();
  60. 60 } catch (InstantiationException e) {
  61. 61 e.printStackTrace();
  62. 62 } catch (IllegalAccessException e) {
  63. 63 e.printStackTrace();
  64. 64 }
  65. 65 return obj;
  66. 66 }
  67. 67
  68. 68 @Override
  69. 69 public T select(T t) {
  70. 70 StringBuffer sqlb = new StringBuffer();
  71. 71 // 通过反射获取实体类中的所有变量
  72. 72 Field fields[] = EntityClass.getDeclaredFields();
  73. 73 sqlb.append("select * from " + EntityClass.getSimpleName() + " where id=?");
  74. 74 T obj = null;
  75. 75 try {
  76. 76 conn = ConnectionManager.getConnection();
  77. 77 ps = conn.prepareStatement(sqlb.toString());
  78. 78 fields[0].setAccessible(true);
  79. 79 ps.setInt(1, (int) fields[0].get(t));
  80. 80 rs = ps.executeQuery();
  81. 81 fields = EntityClass.getDeclaredFields();
  82. 82 while (rs.next()) {
  83. 83 obj = EntityClass.newInstance();
  84. 84 for (int i = 0; i < fields.length; i++) {
  85. 85 fields[i].setAccessible(true);
  86. 86 fields[i].set(obj, rs.getObject(fields[i].getName()));
  87. 87 }
  88. 88 }
  89. 89
  90. 90 } catch (SQLException e) {
  91. 91 e.printStackTrace();
  92. 92 } catch (InstantiationException e) {
  93. 93 e.printStackTrace();
  94. 94 } catch (IllegalAccessException e) {
  95. 95 e.printStackTrace();
  96. 96 }
  97. 97 return obj;
  98. 98 }
  99. 99
  100. 100 // insert into User(id,username,password) values (?,?,?);
  101. 101 @Override
  102. 102 public void add(T t) {
  103. 103 StringBuffer sql = new StringBuffer();
  104. 104 Field fields[] = EntityClass.getDeclaredFields();
  105. 105 sql.append("insert into " + EntityClass.getSimpleName());
  106. 106 sql.append("(");
  107. 107 for (int i = 0; fields != null && i < fields.length; i++) {
  108. 108 fields[i].setAccessible(true); // 这句话必须要有,否则会抛出异常.
  109. 109 String column = fields[i].getName();
  110. 110 sql.append(column).append(",");
  111. 111 }
  112. 112 sql = sql.deleteCharAt(sql.length() - 1);// 删除最后一个,
  113. 113 sql.append(") values (");
  114. 114 for (int i = 0; fields != null && i < fields.length; i++) {
  115. 115 sql.append("?,");
  116. 116 }
  117. 117 sql.deleteCharAt(sql.length() - 1);// 删除最后一个,
  118. 118 sql.append(")");
  119. 119 try {
  120. 120 conn = ConnectionManager.getConnection();
  121. 121 ps = conn.prepareStatement(sql.toString());
  122. 122 Object obj[] = new Object[fields.length];
  123. 123 for (int i = 0; obj != null && i < fields.length; i++) {
  124. 124 fields[i].setAccessible(true);// AccessibleTest类中的成员变量为private,故必须进行此操
  125. 125 obj[i] = fields[i].get(t);
  126. 126 }
  127. 127
  128. 128 for (int i = 0; i < obj.length; i++) {
  129. 129 ps.setObject(i + 1, obj[i]);
  130. 130 }
  131. 131 ps.executeUpdate();
  132. 132 System.out.println("添加成功");
  133. 133
  134. 134 } catch (SQLException e) {
  135. 135 e.printStackTrace();
  136. 136 } catch (IllegalArgumentException e) {
  137. 137 e.printStackTrace();
  138. 138 } catch (IllegalAccessException e) {
  139. 139 e.printStackTrace();
  140. 140 } finally {
  141. 141 try {
  142. 142 ps.close();
  143. 143 } catch (SQLException e) {
  144. 144 e.printStackTrace();
  145. 145 }
  146. 146 try {
  147. 147 conn.close();
  148. 148 } catch (SQLException e) {
  149. 149 e.printStackTrace();
  150. 150 }
  151. 151 }
  152. 152
  153. 153 }
  154. 154
  155. 155 // update User set username=?,password=? where id=?
  156. 156 @Override
  157. 157 public void update(T t) {
  158. 158 StringBuffer sql = new StringBuffer();
  159. 159 Field fields[] = EntityClass.getDeclaredFields();
  160. 160 sql.append("update " + EntityClass.getSimpleName() + " set ");
  161. 161 for (int i = 0; fields != null && i < fields.length; i++) {
  162. 162 fields[i].setAccessible(true);
  163. 163 String column = fields[i].getName();
  164. 164 if (column.equals("id")) {
  165. 165 continue;
  166. 166 }
  167. 167 sql.append(column).append("=").append("?,");
  168. 168 }
  169. 169 sql.deleteCharAt(sql.length() - 1);
  170. 170 sql.append(" where id=?");
  171. 171
  172. 172 try {
  173. 173 conn = ConnectionManager.getConnection();
  174. 174 ps = conn.prepareStatement(sql.toString());
  175. 175
  176. 176 Object Tempobj[] = new Object[fields.length];
  177. 177 for (int i = 0; Tempobj != null && i < fields.length; i++) {
  178. 178 fields[i].setAccessible(true);
  179. 179 Tempobj[i] = fields[i].get(t);
  180. 180 }
  181. 181 Object obj[] = new Object[fields.length];
  182. 182 System.arraycopy(Tempobj, 1, obj, 0, Tempobj.length - 1);
  183. 183 obj[obj.length - 1] = Tempobj[0];
  184. 184
  185. 185 for (int i = 0; i < obj.length; i++) {
  186. 186 ps.setObject(i + 1, obj[i]);
  187. 187 }
  188. 188
  189. 189 ps.executeUpdate();
  190. 190 System.out.println("更新成功");
  191. 191
  192. 192 } catch (SQLException e) {
  193. 193 e.printStackTrace();
  194. 194 } catch (IllegalArgumentException e) {
  195. 195 e.printStackTrace();
  196. 196 } catch (IllegalAccessException e) {
  197. 197 e.printStackTrace();
  198. 198 } finally {
  199. 199 try {
  200. 200 ps.close();
  201. 201 } catch (SQLException e) {
  202. 202 e.printStackTrace();
  203. 203 }
  204. 204 try {
  205. 205 conn.close();
  206. 206 } catch (SQLException e) {
  207. 207 e.printStackTrace();
  208. 208 }
  209. 209 }
  210. 210
  211. 211 }
  212. 212
  213. 213 @Override
  214. 214 public void delete(T t) {
  215. 215 StringBuffer sql = new StringBuffer();
  216. 216 Field fields[] = EntityClass.getDeclaredFields();
  217. 217
  218. 218 sql.append("delete from " + EntityClass.getSimpleName() + " where id=?");
  219. 219
  220. 220 try {
  221. 221 conn = ConnectionManager.getConnection();
  222. 222 ps = conn.prepareStatement(sql.toString());
  223. 223
  224. 224 Object obj[] = new Object[1];
  225. 225 fields[0].setAccessible(true);
  226. 226 obj[0] = fields[0].get(t);
  227. 227
  228. 228 for (int i = 0; i < obj.length; i++) {// 设置参数
  229. 229 ps.setObject(i + 1, obj[i]);
  230. 230 }
  231. 231
  232. 232 ps.executeUpdate();
  233. 233 System.out.println("删除成功");
  234. 234
  235. 235 } catch (SQLException e) {
  236. 236 e.printStackTrace();
  237. 237 } catch (IllegalArgumentException e) {
  238. 238 e.printStackTrace();
  239. 239 } catch (IllegalAccessException e) {
  240. 240 e.printStackTrace();
  241. 241 } finally {
  242. 242 try {
  243. 243 ps.close();
  244. 244 } catch (SQLException e) {
  245. 245 e.printStackTrace();
  246. 246 }
  247. 247 try {
  248. 248 conn.close();
  249. 249 } catch (SQLException e) {
  250. 250 e.printStackTrace();
  251. 251 }
  252. 252 }
  253. 253
  254. 254 }
  255. 255
  256. 256 }

BaseDaoImpl实现类

UserDaoImpl实现类:这是用户的实现类,继承了BaseDaoImpl并且实现 UserDao

  1. package zhr.daoimpl;
  2.  
  3. import java.lang.reflect.ParameterizedType;
  4. import java.sql.Connection;
  5. import java.sql.PreparedStatement;
  6. import java.sql.ResultSet;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9.  
  10. import util.ConnectionManager;
  11. import zhr.bean.User;
  12. import zhr.dao.UserDao;
  13.  
  14. public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {
  15.  
  16. private Connection conn;
  17. private PreparedStatement ps;
  18. private ResultSet rs;
  19. private Class<User> EntityClass;// 获取实体类
  20. private List<User> list;
  21. private String sql;
  22.  
  23. public UserDaoImpl() {
  24. /**
  25. * 传递User就是 com.example.daoimp.BaseDaoImpl<com.example.bean.User> 传递Shop就是
  26. * com.example.daoimp.BaseDaoImpl<com.example.bean.Shop>
  27. */
  28. ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
  29. /**
  30. * 这里如果传递的是User.那么就是class com.example.bean.User 如果传递的是Shop. 那么就是class
  31. * com.example.bean.Shop
  32. */
  33.  
  34. EntityClass = (Class<User>) type.getActualTypeArguments()[0];
  35. }
  36.  
  37. @Override
  38. public List<User> findAll() {
  39. StringBuffer b = new StringBuffer();
  40. list = new ArrayList<User>();
  41. sql = b.append("select * from " + EntityClass.getSimpleName()).toString();
  42. try {
  43. conn = ConnectionManager.getConnection();
  44. ps = conn.prepareStatement(sql);
  45. rs = ps.executeQuery();
  46. while (rs.next()) {
  47. User user = new User();
  48. user.setId(rs.getInt("id"));
  49. user.setUsername(rs.getString("username"));
  50. user.setPassword(rs.getString("password"));
  51. list.add(user);
  52. }
  53. } catch (Exception e) {
  54. e.printStackTrace();
  55. }
  56. return list;
  57. }
  58.  
  59. }

ConnectionManager工具类:主要用来获取连接Connection

  1. package util;
  2.  
  3. import java.sql.Connection;
  4. import java.sql.DriverManager;
  5. import java.sql.SQLException;
  6.  
  7. public class ConnectionManager {
  8. public static Connection getConnection() {
  9. Connection conn = null;
  10. String url = "jdbc:mysql://localhost:3306/test";
  11. String username = "root";
  12. String password = "root";
  13. try {
  14. Class.forName("com.mysql.jdbc.Driver");
  15. conn = DriverManager.getConnection(url, username, password);
  16. } catch (ClassNotFoundException e) {
  17. e.printStackTrace();
  18. System.out.println("没有找到文件");
  19. } catch (SQLException e) {
  20. e.printStackTrace();
  21. System.out.println("sql异常");
  22. }
  23. return conn;
  24. }
  25. }

测试类:

  1. ackage zhr.test;
  2.  
  3. import java.util.List;
  4.  
  5. import zhr.bean.User;
  6. import zhr.dao.UserDao;
  7. import zhr.daoimpl.UserDaoImpl;
  8.  
  9. public class Test {
  10. public static void main(String[] args) {
  11. List<User> list = null;
  12. UserDaoImpl imp = new UserDaoImpl();
  13. list = imp.findAll();
  14. for (User user : list) {
  15. System.out.println(user.getId() + " " + user.getUsername() + " " + user.getPassword());
  16. }
  17. // 查询
  18. User ua = (User) imp.selectByID(1);// 通过id查询User
  19. System.out.println(ua.getClass().getSimpleName());
  20. System.out.println(ua);
  21. System.out.println(ua.getId() + " " + ua.getUsername() + " " + ua.getPassword());
  22.  
  23. /*
  24. * 添加操作 User user = new User(); user.setId(11); user.setUsername("zhr");
  25. * user.setPassword("123456"); imp.add(user);
  26. */
  27.  
  28. /*
  29. * 更新操作 User user1 = new User(); user1.setId(1); user1.setUsername("hhh");
  30. * user1.setPassword("123"); imp.update(user1);
  31. */
  32.  
  33. /*
  34. * 删除操作 User user2 = new User(); user2.setId(11); user2.setUsername("zhr");
  35. * user2.setPassword("123456"); imp.delete(user2);
  36. */
  37.  
  38. }
  39. }

时隔一年,再次写博客,希望大家互相支持,相互学习,有不对的地方可以评论留言。记得粉我噢~谢谢大家。

泛型DAO的更多相关文章

  1. 泛型DAO与泛型Service

    泛型Dao与Service 看了几个帖子,泛型Dao与Service的主要目的就是要减少重复代码.具体的说明如下: 1. 定义一个BaseDao接口,此接口包含了一些通用的DAO操作,例如:增加.删除 ...

  2. 一个好用的hibernate泛型dao

    以前从springside2.0上搞下来的很好用的,基本实现dao零编码只要配置xml文件就行了. 先看图: 一共4层,com.demonstration.hibernate.basedao是我加的用 ...

  3. SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装

    SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装 >>>>>>>& ...

  4. 《项目架构那点儿事》——Hibernate泛型Dao,让持久层简洁起来

    [前言]hibernate作为持久层ORM技术,它对JDBC进行非常轻量级对象封装,使得我们可以随心所欲的使用面向对象的思想来操作数据 库.同时,作为后台开发的支撑,的确扮演了一个举足轻重的角色,那么 ...

  5. 自己动手写泛型dao

    在经过一系列的问题得到解决之后,泛型dao终于写出来了.泛型dao相比于以前写的dao最大的好处就是,大大提高了代码的复用性,以往我们要对数据库中表中的数据进行操作的时候,每张表都需要写一个dao来操 ...

  6. 浅谈Java——泛型DAO

    首先解释一下为什么要学习泛型DAO.平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写很多的操作数据库的方法.当我们有很多的javaben的时候我们会写很多的接口和实现类,并且里面的代码都是 ...

  7. JPA的泛型DAO设计及使用

    使用如Hibernate或者JPA作为持久化的解决方案时,设计一个泛型的DAO抽象父类可以方便各个实体的通用CRUD操作.由于此时大部分实体DAO的CRUD操作基本一样,采用泛型设计解决这个问题,带来 ...

  8. Hibernate也须要呵护——Hibernate的泛型DAO

    众所周之.面向对象的基础是抽象.也能够说,抽象促使编程在不断发展. 对于数据库的訪问,以前写过HqlHelper.EFHelper.编写Spring+Hibernate框架下的应用.也相同离不了编写一 ...

  9. 泛型DAO模型设计

    aaarticlea/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKC

随机推荐

  1. 深入浅出数据结构C语言版(22)——排序决策树与桶式排序

    在(17)中我们对排序算法进行了简单的分析,并得出了两个结论: 1.只进行相邻元素交换的排序算法时间复杂度为O(N2) 2.要想时间复杂度低于O(N2),算法必须进行远距离的元素交换 而今天,我们将对 ...

  2. Free Goodies UVA - 12260 贪心

      Free Goodies Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Submit ...

  3. 简单Elixir游戏服设计-玩法simple_poker

    上回介绍了玩法,现在编写了玩法的简单建模. 做到现在感觉目前还没有使用umbrella的必要(也许以后会发现必要吧),model 应用完全可以合并到game_server. 代码还在https://g ...

  4. 【疑问】用python写登录验证遇到的问题

    最近开始断断续续学习python,今天加入博客园,作为新人,和各位老师们讨教了,以后多多照顾!为了大家能看清楚所以就截图了,文末尾附源码,说不定会有那位老师给我指教一番.############### ...

  5. Mysql [Err] 1293 there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

    问题: mysql数据 导入数据出错 [Err] 1293 - Incorrect table definition; there can be only one TIMESTAMP column w ...

  6. 关于AOP装饰函数中的this

    在学习关于JavaScript的装饰者设计模式的过程中,发现其实现方式的关键在于this的使用. 想象一个匿名函数(其实预定义的有名函数也可以,都存在引用),其中的this: // 我们先定义一个匿名 ...

  7. WPF 只允许打开一个实例

    我们有时候只希望我们的程序只打开一个实例,也就是我们的软件只有一次被打开. 那么我们可以通过一个办法知道,在这个软件打开前是不是打开过一个,还没关闭.也就是是否存在另一个程序在运行. 下面是一个简单方 ...

  8. 关于Java和JavaScript对字符串截取处理的总结

    在JavaWeb开发中,经常需要对字符串进行处理,包括Java语言和JS语言,总是容易弄混淆,这里简单对比一下两种语言对于字符串截取方法. 一.先看Java public class StringDe ...

  9. Java 7 JVM和垃圾收集

    ---恢复内容开始--- 写JAVA程序,一定要了解JVM(JAVA Virtual machine)一些基础知识和垃圾收集.如果对JVM已经很了解了,可以不用继续往下阅读了.本文只针对Java 7, ...

  10. C 结构体零散知识点

    1.结构体无法把自己作为成员,但可以包含指向自己的指针成员 2.定义不完整结构类型(类型,结构,占用空间无法确定,如void指针,声明没有指明数组长度数组)只能使用小标签,即struct struct ...