浅谈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个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
随机推荐
- 使用OpenGL绘制 shapefile文件 完成最基本的gis操作
主要内容概述 (视频教程已经发布:http://edu.csdn.net/course/detail/3422) (http://edu.csdn.net/course/detail/3420) 1. ...
- 图解安卓-c++开发-通过java 调用c++ jni的使用
接着上一节 ,很多事情用java做,效率要差一点(尤其是游戏),所以要用c++来实现,那么java如何调用c++ 首先建议一个工程 HelloJni如下图: 按照默认的配置下一步,直到完成 . 如下图 ...
- Spring+Druid+SpringMVC的搭建(附Demo)
最近公司事情比较少,便想利用这段空闲时间做一个自己的博客. 前端界面已经搞好,感谢杨姐的模板,自己稍微把模板没有的模块给补全了. 今天便开始自己的SSM框架搭建,数据库链接是采用数据库连接池.先上个项 ...
- freepbx13通话无声音通话自动挂断
在阿里云上用脚本一键搭建好了freepbx13,但是在创建好sip分机之后,打电话没有声音,双方都听不到对方的声音.这个是nat问题. 这里有个坑我提醒下大家,就是我们最好不要用台式电脑进行测试通话. ...
- (转) Java我的高效编程之环境搭建
前言:刚毕业, 工作之余写博客有利于提高技术,更是能帮助人,接下来会认认真真写好每一篇博客.希望大家多多支持.废话不多说,马上开始.这是一篇环境搭建的博客. jdk+eclipse+svn+maven ...
- Firebird 获取用户表及字段
select rdb$relation_fields.rdb$relation_name table_name, rdb$relations.rdb$description table_des, rd ...
- Ionic开发之如何修改Cordova插件
由于大多数的Cordova plugin都是国外的,一些提示信息通常都是英文, 这就需要我们自己修改成中文信息. 除此之外,还有可能插件的样式,皮肤等和整体项目的风格不一致,这个时候也是要修改的. 可 ...
- mybatis在mysql中的分页扩展
applicationContext.xml <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlS ...
- Hive配置文件hive-site.xml
<configuration> <property> <name>hive.metastore.warehouse.dir</name> <val ...
- 关于Java中语句符号及格式的理解
关于Java中语句符号及格式的理解 这篇文章是撰写的第一篇文章,在此作一下博主是一名在读的工科研究生,种种原因,研二开始决定转行从事程序员工作.开始的自学之路并不算非常顺畅,也走了一点弯路,但一直都坚 ...