首先解释一下为何要学习泛型DAO。平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写不少的操做数据库的方法。当咱们有不少的javaben的时候咱们会写不少的接口和实现类,而且里面的代码都是相同的,这样太麻烦,咱们就不能写一个类,在类里面传入泛型,让类根据泛型,建立出一个实例对象,这样就出现了泛型DAO。java
1、须要提早准备的知识以下mysql
反射关键的类:sql
Class<T>类 是java.lang包下,Class类的实例表示正在运行的 Java 应用中的类和接口。数据库
Type接口 是java.lang.reflect包下的是Java类型的通用超级接口。这些包括原始类型,参数化类型,数组类型和类型变量数组
ParameterizedType接口 是java.lang.reflect包下是Type的子接口,表示一个参数化类型,如Collection<String>app
Field类 是java.lang.reflect包下,提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段多是一个类(静态)字段或实体字段ide
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 则实施访问检查
2、下面是泛型DAO的源码
User实体类:主要声明一个实体,get、set方法来获取实体的属性
1 package zhr.bean; 2 3 public class User { 4 private int id; 5 private String username; 6 private String password; 7 8 public int getId() { 9 return id; 10 } 11 12 public void setId(int id) { 13 this.id = id; 14 } 15 16 public String getUsername() { 17 return username; 18 } 19 20 public void setUsername(String username) { 21 this.username = username; 22 } 23 24 public String getPassword() { 25 return password; 26 } 27 28 public void setPassword(String password) { 29 this.password = password; 30 } 31 32 @Override 33 public String toString() { 34 return "User [id=" + id + ", username=" + username + ", password=" + password + "]"; 35 } 36 37 }
BaseDao接口:用来写泛型DAO的核心接口主要就是一些增删改查的方法
1 package zhr.dao; 2 3 public interface BaseDao<T> { 4 T selectByID(int id); 5 6 T select(T t); 7 8 void add(T t); 9 10 void update(T t); 11 12 void delete(T t); 13 }
UserDao接口:主要DAO接口,相似的DAO接口也能够写这样只须要继承BaseDao接口就能够,提升了代码的复用性,也能够本身定义功能方法
1 package zhr.dao; 2 3 import java.util.List; 4 5 import zhr.bean.User; 6 7 public interface UserDao extends BaseDao<User> { 8 List<User> findAll(); 9 }
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 }
UserDaoImpl实现类:这是用户的实现类,继承了BaseDaoImpl而且实现 UserDao
1 package zhr.daoimpl; 2 3 import java.lang.reflect.ParameterizedType; 4 import java.sql.Connection; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.util.ArrayList; 8 import java.util.List; 9 10 import util.ConnectionManager; 11 import zhr.bean.User; 12 import zhr.dao.UserDao; 13 14 public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao { 15 16 private Connection conn; 17 private PreparedStatement ps; 18 private ResultSet rs; 19 private Class<User> EntityClass;// 获取实体类 20 private List<User> list; 21 private String sql; 22 23 public UserDaoImpl() { 24 /** 25 * 传递User就是 com.example.daoimp.BaseDaoImpl<com.example.bean.User> 传递Shop就是 26 * com.example.daoimp.BaseDaoImpl<com.example.bean.Shop> 27 */ 28 ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass(); 29 /** 30 * 这里若是传递的是User.那么就是class com.example.bean.User 若是传递的是Shop. 那么就是class 31 * com.example.bean.Shop 32 */ 33 34 EntityClass = (Class<User>) type.getActualTypeArguments()[0]; 35 } 36 37 @Override 38 public List<User> findAll() { 39 StringBuffer b = new StringBuffer(); 40 list = new ArrayList<User>(); 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 = new User(); 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 return list; 57 } 58 59 }
ConnectionManager工具类:主要用来获取链接Connection
1 package util; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.SQLException; 6 7 public class ConnectionManager { 8 public static Connection 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 return conn; 24 } 25 }
测试类:
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); */ } }
时隔一年,再次写博客,但愿你们互相支持,相互学习,有不对的地方能够评论留言。记得粉我噢~谢谢你们。