泛型DAO
最近正在學習泛型DAO,通過網上查閱資料,匯總並自己整理了一下。提前需要學習的知識java反射、泛型
用到的反射如下:
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語言訪問控制檢查的能力
有人肯定會問什麽是參數化類型?
參數化類型就是一個編譯器可以自動定制作用於特定類型上的類,個人理解就是泛型
什麽是原始類型?
一個原始類型就是一個沒有任何類型參數的泛型類或者泛型接口的名字。
eg:List<E> 是一個泛型接口,List<String>是一個參數化的類型,List就是一個原生類型
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實體類:
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接口:
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接口:
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實現類:
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實現類:
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工具類:
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); */ } }
時隔一年,再次寫博客,希望大家互相支持,相互學習,有不對的地方可以評論留言。記得粉我噢~謝謝大家。
泛型DAO