浅谈Java——泛型DAO
首先解释一下为什么要学习泛型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的更多相关文章
- 浅谈Java泛型之<? extends T>和<? super T>的区别
关于Java泛型,这里我不想总结它是什么,这个百度一下一大堆解释,各种java的书籍中也有明确的定义,只要稍微看一下就能很快清楚.从泛型的英文名字Generic type也能看出,Generic普通. ...
- 浅谈Java泛型中的extends和super关键字(转)
通配符 在本文的前面的部分里已经说过了泛型类型的子类型的不相关性.但有些时候,我们希望能够像使用普通类型那样使用泛型类型: 向上造型一个泛型对象的引用 向下造型一个泛型对象的引用 向上造型一个泛型对象 ...
- 浅谈Java泛型中的extends和super关键字
泛型是在Java 1.5中被加入了,这里不讨论泛型的细节问题,这个在Thinking in Java第四版中讲的非常清楚,这里要讲的是super和extends关键字,以及在使用这两个关键字的时候为什 ...
- 浅谈Java泛型中的? extends E和?super E
https://blog.csdn.net/zymx14/article/details/78073757
- 浅谈java类集框架和数据结构(2)
继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...
- 浅谈Java的反射机制和作用
浅谈Java的反射机制和作用 作者:Java大师 欢迎转载,转载请注明出处 很多刚学Java反射的同学可能对反射技术一头雾水,为什么要学习反射,学习反射有什么作用,不用反射,通过new也能创建用户对象 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
- 浅谈Java中的对象和引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
随机推荐
- require/load/include/extend的区别
require 一般用于加载一个库,当多次使用require加载一个库时,只有第一次有效,后面的都会加载失败,也就是会返回"false",以为require会追踪文件是否被加载. ...
- centos7上安装redis
关闭防火墙:systemctl stop firewalld.service #停止firewallsystemctl disable firewalld.service #禁止firewall开机启 ...
- Google Guava--基础工具用法
Optional 优雅的解决Null(java 8 提供了Optional类) Guava用Optional表示可能为null的T类型引用.一个Optional实例可能包含非null的引用(我们称之为 ...
- 基于线程实现的生产者消费者模型(Object.wait(),Object.notify()方法)
需求背景 利用线程来模拟生产者和消费者模型 系统建模 这个系统涉及到三个角色,生产者,消费者,任务队列,三个角色之间的关系非常简单,生产者和消费者拥有一个任务队列的引用,生产者负责往队列中放置对象(i ...
- 国际化实现之安装脚手架vue以及打包问题
做这个项目用的是vue+element UI来实现的响应式布局,现主要说一下国际化这块的实现. 第一步:新建文件夹i18n 第二步:配置cn.js.en.js等文件内容 cn.js import en ...
- 分布式改造剧集三:Ehcache分布式改造
第三集:分布式Ehcache缓存改造 前言 好久没有写博客了,大有半途而废的趋势.忙不是借口,这个好习惯还是要继续坚持.前面我承诺的第一期的DIY分布式,是时候上终篇了---DIY分布式缓存. 探 ...
- 深入了解Java虚拟机(3)类文件结构
虚拟机执行子系统 一.类文件结构 1.魔数和class版本 1.magic-魔数:0xCAFEBABE:4字节 2.minor_version:次版本,丶之后的数字:2字节 3.major_versi ...
- C#byte类型
byte类型的范围是0~255转换为二进制是00000000~11111111 ---------------------------------------------------------- C ...
- c#基础学习(0630)之面向对象总习
面向对象总习 1.封装.继承.多态 ****字段:存储数据,访问修饰符应该设置为private私有的 ****属性:保护字段,对字段的取值和赋值的限定 ****new关键字: 1.在堆中开辟空间(引用 ...
- @EnableAutoConfiguration和@SpringbootApplication注解
一.@EnableAutoConfiguration 这个注释告诉SpringBoot“猜”你将如何想配置Spring,基于你已经添加jar依赖项.如果spring-boot-starter-web已 ...