首先解释一下为什么要学习泛型DAO。平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写很多的操作数据库的方法。当我们有很多的javaben的时候我们会写很多的接口和实现类,并且里面的代码都是相同的,这样太麻烦,我们就不能写一个类,在类里面传入泛型,让类根据泛型,创建出一个实例对象,这样就出现了泛型DAO。
一、需要提前准备的知识如下
反射关键的类:
Class类 是java.lang包下,Class类的实例表示正在运行的 Java 应用中的类和接口。
Type接口 是java.lang.reflect包下的是Java类型的通用超级接口。这些包括原始类型,参数化类型,数组类型和类型变量
ParameterizedType接口 是java.lang.reflect包下是Type的子接口,表示一个参数化类型,如Collection
Field类 是java.lang.reflect包下,提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实体字段
AccessibleObject类 是java.lang.reflect包下,是Filed、Method和Constructor对象的基类。提供了将反射的对象标记为在使用时取消默认 Java语言访问控制检查的能力
反射关键的方法:
ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
//getGenericSuperclass() 返回此Class 所有的实体(类、接口、基本类型或者void)的直接超类的 Type
Class entityClass = (Class) type.getActualTypeArguments()[0];
//getActualTypeArguments() 返回此类型的实际类型参数的数组Type对象
getDeclaredFields() 返回 Field 对象的一个数组,这些对象所表示的类或接口所声明的所有字段。(公共、保护、默认、私有字段,不包括继承的字段)
newInstance() 创建此 Class 对象的新实例
setAccessible(boolean flag) 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则实施访问检查
二、下面是泛型DAO的源码
User实体类:主要声明一个实体,get、set方法来获取实体的属性
1 packagezhr.bean;2
3 public classUser {4 private intid;5 privateString username;6 privateString password;7
8 public intgetId() {9 returnid;10 }11
12 public void setId(intid) {13 this.id =id;14 }15
16 publicString getUsername() {17 returnusername;18 }19
20 public voidsetUsername(String username) {21 this.username =username;22 }23
24 publicString getPassword() {25 returnpassword;26 }27
28 public voidsetPassword(String password) {29 this.password =password;30 }31
32 @Override33 publicString toString() {34 return "User [id=" + id + ", username=" + username + ", password=" + password + "]";35 }36
37 }
BaseDao接口:用来写泛型DAO的核心接口主要就是一些增删改查的方法
1 packagezhr.dao;2
3 public interface BaseDao{4 T selectByID(intid);5
6 T select(T t);7
8 voidadd(T t);9
10 voidupdate(T t);11
12 voiddelete(T t);13 }
UserDao接口:主要DAO接口,类似的DAO接口也可以写这样只需要继承BaseDao接口就可以,提高了代码的复用性,也可以自己定义功能方法
1 packagezhr.dao;2
3 importjava.util.List;4
5 importzhr.bean.User;6
7 public interface UserDao extends BaseDao{8 ListfindAll();9 }
BaseDaoImpl实现类:实现BaseDao接口,构造方法使用了反射获取实体类,这是泛型DAO核心实现类,需要详细写,增删改查,或者更多功能,比如通过id来查询,或者给两个参数查询between and,大于或者小于 核心思想就是反射。
1 packagezhr.daoimpl;2
3 importjava.lang.reflect.Field;4 importjava.lang.reflect.ParameterizedType;5 importjava.sql.Connection;6 importjava.sql.PreparedStatement;7 importjava.sql.ResultSet;8 importjava.sql.SQLException;9
10 importutil.ConnectionManager;11 importzhr.dao.BaseDao;12
13 public class BaseDaoImpl implements BaseDao{14
15 privateConnection conn;16 privatePreparedStatement ps;17 privateResultSet rs;18 private Class EntityClass;//获取实体类
19
20 @SuppressWarnings("unchecked")21 publicBaseDaoImpl() {22 /**23 * 传递User就是 zhr.daoimpl.BaseDaoImpl 传递Shop就是
24 * zhr.daoimpl.BaseDaoImpl
25*/
26 ParameterizedType type =(ParameterizedType) getClass().getGenericSuperclass();27System.out.println(type);28 /**29 * 这里如果传递的是User.那么就是zhr.bean.User 如果传递的是Shop. 那么就是zhr.bean.Shop
30 *
31*/
32
33 EntityClass = (Class) type.getActualTypeArguments()[0];34System.out.println(EntityClass);35}36
37@Override38 public T selectByID(intid) {39 StringBuffer sqlb = newStringBuffer();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);54fields[i].set(obj, rs.getObject(fields[i].getName()));55}56}57
58 } catch(SQLException e) {59e.printStackTrace();60 } catch(InstantiationException e) {61e.printStackTrace();62 } catch(IllegalAccessException e) {63e.printStackTrace();64}65 returnobj;66}67
68@Override69 publicT select(T t) {70 StringBuffer sqlb = newStringBuffer();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);86fields[i].set(obj, rs.getObject(fields[i].getName()));87}88}89
90 } catch(SQLException e) {91e.printStackTrace();92 } catch(InstantiationException e) {93e.printStackTrace();94 } catch(IllegalAccessException e) {95e.printStackTrace();96}97 returnobj;98}99
100 //insert into User(id,username,password) values (?,?,?);
101@Override102 public voidadd(T t) {103 StringBuffer sql = newStringBuffer();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[] = newObject[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}131ps.executeUpdate();132 System.out.println("添加成功");133
134 } catch(SQLException e) {135e.printStackTrace();136 } catch(IllegalArgumentException e) {137e.printStackTrace();138 } catch(IllegalAccessException e) {139e.printStackTrace();140 } finally{141 try{142ps.close();143 } catch(SQLException e) {144e.printStackTrace();145}146 try{147conn.close();148 } catch(SQLException e) {149e.printStackTrace();150}151}152
153}154
155 //update User set username=?,password=? where id=?
156@Override157 public voidupdate(T t) {158 StringBuffer sql = newStringBuffer();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[] = newObject[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[] = newObject[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
189ps.executeUpdate();190 System.out.println("更新成功");191
192 } catch(SQLException e) {193e.printStackTrace();194 } catch(IllegalArgumentException e) {195e.printStackTrace();196 } catch(IllegalAccessException e) {197e.printStackTrace();198 } finally{199 try{200ps.close();201 } catch(SQLException e) {202e.printStackTrace();203}204 try{205conn.close();206 } catch(SQLException e) {207e.printStackTrace();208}209}210
211}212
213@Override214 public voiddelete(T t) {215 StringBuffer sql = newStringBuffer();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
232ps.executeUpdate();233 System.out.println("删除成功");234
235 } catch(SQLException e) {236e.printStackTrace();237 } catch(IllegalArgumentException e) {238e.printStackTrace();239 } catch(IllegalAccessException e) {240e.printStackTrace();241 } finally{242 try{243ps.close();244 } catch(SQLException e) {245e.printStackTrace();246}247 try{248conn.close();249 } catch(SQLException e) {250e.printStackTrace();251}252}253
254}255
256 }
BaseDaoImpl实现类
UserDaoImpl实现类:这是用户的实现类,继承了BaseDaoImpl并且实现 UserDao
1 packagezhr.daoimpl;2
3 importjava.lang.reflect.ParameterizedType;4 importjava.sql.Connection;5 importjava.sql.PreparedStatement;6 importjava.sql.ResultSet;7 importjava.util.ArrayList;8 importjava.util.List;9
10 importutil.ConnectionManager;11 importzhr.bean.User;12 importzhr.dao.UserDao;13
14 public class UserDaoImpl extends BaseDaoImpl implementsUserDao {15
16 privateConnection conn;17 privatePreparedStatement ps;18 privateResultSet rs;19 private Class EntityClass;//获取实体类
20 private Listlist;21 privateString sql;22
23 publicUserDaoImpl() {24 /**
25 * 传递User就是 com.example.daoimp.BaseDaoImpl 传递Shop就是26 * com.example.daoimp.BaseDaoImpl27 */
28 ParameterizedType type =(ParameterizedType) getClass().getGenericSuperclass();29 /**
30 * 这里如果传递的是User.那么就是class com.example.bean.User 如果传递的是Shop. 那么就是class31 * com.example.bean.Shop32 */
33
34 EntityClass = (Class) type.getActualTypeArguments()[0];35 }36
37 @Override38 public ListfindAll() {39 StringBuffer b = newStringBuffer();40 list = new ArrayList();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 = newUser();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 returnlist;57 }58
59 }
ConnectionManager工具类:主要用来获取连接Connection
1 packageutil;2
3 importjava.sql.Connection;4 importjava.sql.DriverManager;5 importjava.sql.SQLException;6
7 public classConnectionManager {8 public staticConnection 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 returnconn;24 }25 }
测试类:
ackage zhr.test;importjava.util.List;importzhr.bean.User;importzhr.dao.UserDao;importzhr.daoimpl.UserDaoImpl;public classTest {public static voidmain(String[] args) {
List list = null;
UserDaoImpl imp= newUserDaoImpl();
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);*/}
}
时隔一年,再次写博客,希望大家互相支持,相互学习,有不对的地方可以评论留言。记得粉我噢~谢谢大家。