首先解释一下为什么要学习泛型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方法来获取实体的属性

 package zhr.bean;

 public class User {
private int id;
private String username;
private String password; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} @Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
} }

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

 package zhr.dao;

 public interface BaseDao<T> {
T selectByID(int id); T select(T t); void add(T t); void update(T t); void delete(T t);
}

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

 package zhr.dao;

 import java.util.List;

 import zhr.bean.User;

 public interface UserDao extends BaseDao<User> {
List<User> findAll();
}

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

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

BaseDaoImpl实现类

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

 package zhr.daoimpl;

 import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List; import util.ConnectionManager;
import zhr.bean.User;
import zhr.dao.UserDao; public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao { private Connection conn;
private PreparedStatement ps;
private ResultSet rs;
private Class<User> EntityClass;// 获取实体类
private List<User> list;
private String sql; public UserDaoImpl() {
/**
* 传递User就是 com.example.daoimp.BaseDaoImpl<com.example.bean.User> 传递Shop就是
* com.example.daoimp.BaseDaoImpl<com.example.bean.Shop>
*/
ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
/**
* 这里如果传递的是User.那么就是class com.example.bean.User 如果传递的是Shop. 那么就是class
* com.example.bean.Shop
*/ EntityClass = (Class<User>) type.getActualTypeArguments()[0];
} @Override
public List<User> findAll() {
StringBuffer b = new StringBuffer();
list = new ArrayList<User>();
sql = b.append("select * from " + EntityClass.getSimpleName()).toString();
try {
conn = ConnectionManager.getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
list.add(user);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
} }

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

 package util;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException; public class ConnectionManager {
public static Connection getConnection() {
Connection conn = null;
String url = "jdbc:mysql://localhost:3306/test";
String username = "root";
String password = "root";
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.out.println("没有找到文件");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("sql异常");
}
return conn;
}
}

测试类:

ackage zhr.test;

import java.util.List;

import zhr.bean.User;
import zhr.dao.UserDao;
import zhr.daoimpl.UserDaoImpl; public class Test {
public static void main(String[] args) {
List<User> list = null;
UserDaoImpl imp = new UserDaoImpl();
list = imp.findAll();
for (User user : list) {
System.out.println(user.getId() + " " + user.getUsername() + " " + user.getPassword());
}
// 查询
User ua = (User) imp.selectByID(1);// 通过id查询User
System.out.println(ua.getClass().getSimpleName());
System.out.println(ua);
System.out.println(ua.getId() + " " + ua.getUsername() + " " + ua.getPassword()); /*
* 添加操作 User user = new User(); user.setId(11); user.setUsername("zhr");
* user.setPassword("123456"); imp.add(user);
*/ /*
* 更新操作 User user1 = new User(); user1.setId(1); user1.setUsername("hhh");
* user1.setPassword("123"); imp.update(user1);
*/ /*
* 删除操作 User user2 = new User(); user2.setId(11); user2.setUsername("zhr");
* user2.setPassword("123456"); imp.delete(user2);
*/ }
}

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

浅谈Java——泛型DAO的更多相关文章

  1. 浅谈Java泛型之<? extends T>和<? super T>的区别

    关于Java泛型,这里我不想总结它是什么,这个百度一下一大堆解释,各种java的书籍中也有明确的定义,只要稍微看一下就能很快清楚.从泛型的英文名字Generic type也能看出,Generic普通. ...

  2. 浅谈Java泛型中的extends和super关键字(转)

    通配符 在本文的前面的部分里已经说过了泛型类型的子类型的不相关性.但有些时候,我们希望能够像使用普通类型那样使用泛型类型: 向上造型一个泛型对象的引用 向下造型一个泛型对象的引用 向上造型一个泛型对象 ...

  3. 浅谈Java泛型中的extends和super关键字

    泛型是在Java 1.5中被加入了,这里不讨论泛型的细节问题,这个在Thinking in Java第四版中讲的非常清楚,这里要讲的是super和extends关键字,以及在使用这两个关键字的时候为什 ...

  4. 浅谈Java泛型中的? extends E和?super E

    https://blog.csdn.net/zymx14/article/details/78073757

  5. 浅谈java类集框架和数据结构(2)

    继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...

  6. 浅谈Java的反射机制和作用

    浅谈Java的反射机制和作用 作者:Java大师 欢迎转载,转载请注明出处 很多刚学Java反射的同学可能对反射技术一头雾水,为什么要学习反射,学习反射有什么作用,不用反射,通过new也能创建用户对象 ...

  7. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  8. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  9. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

随机推荐

  1. certificate verify fails (https://gems.ruby-china.org错误

    首先:执行这一步报错的背景是: 更换gems源, 通常执行 gem sources --add https://gems.ruby-china.org/ --remove https://rubyge ...

  2. css 实现元素长宽等比缩放

    实现思路(长宽比2:1): 以父级元素为基准, 子级 width:100%; (也就是父级宽度的 100%), padding-top:50% (也就是父级宽度的 50%, 根据 css 规范, pa ...

  3. gitHub-高仿58同城加载动画

    导入方式: /build.gradle repositories { maven { url "https://jitpack.io" } } /app/build.gradle ...

  4. Python虚拟环境中pip install时没有权限问题

    virtualenv Permission denied 新建的python虚拟环境的目录的所属者必须是当前用户,才不会出现这种错误 比如 virtualenv py27 sudo chown zzf ...

  5. Linux-(diff)

    diff 命令 1.命令格式: diff  [参数]  [文件1或目录1]  [文件2或目录2] 2.命令功能: diff命令能比较单个文件或者目录内容.如果指定比较的是文件,则只有当输入为文本文件时 ...

  6. Ruby语言学习系列--String 类函数

        函数名称 说明 示例 * 将字符串拷贝N次 “ha”*4    >> “hahahaha” + <<  concat 连接字符串 “yes” + “no”  >& ...

  7. JavaScript初级面试题

    前面几题是会很基础,越下越有深度. 初级Javascript: 1.JavaScript是一门什么样的语言,它有哪些特点? 没有标准答案. 2.JavaScript的数据类型都有什么? 基本数据类型: ...

  8. 解决升级Nodepad++都会让插件失效

    主要原因是Plugin Manager失效导致的,需要重新导入 导入一下PluginManager就可以了地址:https://github.com/bruderstein/nppPluginMana ...

  9. 大话JVM(一):垃圾收集算法

     系列介绍|本系列主要是记录学习jvm过程中觉得重要的内容,方便以后复习 在说垃圾收集算法之前,先要说一下垃圾收集,从大的讲,垃圾收集需要考虑三件事情: 1.哪些内存需要回收 2.什么时候回收 3.如 ...

  10. front-end 前端发展学习路线参考图

    front-end 前端发展学习路线参考图 学习的路程还很长~!