泛型DAO

时间:2023-03-09 08:15:35
泛型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);
*/ }
}

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