JDBC:利用反射封裝增刪改查操作
阿新 • • 發佈:2019-02-08
在學習了反射之後,知道了反射機制的強大,可以做很多事情。可以利用反射實現動態語言的部分特徵;可以利用反射獲取類的結構資訊,動態呼叫屬性和方法等等。因此,本文通過利用反射對JDBC的增刪改查的封裝加深對反射機制的瞭解。
1.反射的一些常用方法:
1.1、獲取Class的例項(三種):
- Class c = 類名.class
- Class c = Class.forName("類的全限定類名");
- Class c = 物件.getClass();
1.2、獲取物件的類名
- String className = c.getName(); // 獲取全限定類名
- String className = c.getSimpleName(); //獲取簡單類名
1.3、獲取Field(四個方法):
- Field field = c.getField("屬性名"); //該方法只能通過屬性名獲取public的屬性
- Field[] field = c.getFields(); //獲取所有的public屬性陣列
- Field field = c.getDeclaredField("屬性名"); //獲取類的屬性,包括protected/private
1.4、獲取Field的資訊
- String name = field.getName(); //獲取屬性名
- Class<?> type = field.getType(); //獲取屬性的型別
- Object value = field.get(obj); //獲取obj物件的field屬性的值
- field.set(obj,Object value); //給obj物件的field屬性賦值value
1.5、設定可訪問性
- setAccessible(true); //可以用在被訪問修飾符修飾的地方,
//預設為false只能對public修飾的操作,設定true 可對private修飾的操作
2. 對增刪改查的封裝,只需要把一個物件當做引數轉入方法即可
2.1、插入
/**
* 類名對應表,屬性對應欄位
* @param obj 傳入的物件
* @return
*/
public static boolean insert(Object obj) {
boolean flag = false;
Class<?> c = obj.getClass(); //獲取obj的Class
//利用StringBuffer進行插入SQL語句的構造
//通過反射獲取類名對映表名
StringBuffer sb1 = new StringBuffer("insert into "+ c.getSimpleName() +"(");
StringBuffer sb2 = new StringBuffer(" values(");
Field[] field = c.getDeclaredFields(); //通過反射獲取物件的屬性陣列
for(int i = 0; i < field.length; i++) { //遍歷屬性構造SQL語句
if(i != field.length-1) {
sb1.append(field[i].getName()).append(",");
sb2.append("?,");
}else {
sb1.append(field[i].getName()).append(")");
sb2.append("?);");
}
}
String sql = sb1.append(sb2).toString();
//獲取資料庫連線,進行資料庫操作
Connection conn = getConnection();
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
for(int i = 0; i < field.length; i++) {
field[i].setAccessible(true); //設定屬性的可訪問性,可以訪問私有屬性
try { //通過Field的get(Object)方法獲取Object物件的屬性值
ps.setObject(i+1, field[i].get(obj)); //對預編譯的SQL語句中的?進行賦值
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
System.out.println(ps); //返回執行的SQL語句
flag = ps.execute(); //執行SQL
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(ps);
close(conn);
}
return flag;
}
2.2、刪除
/**
* 通過主鍵(預設第一個屬性)刪除物件
* @param obj
* @return
*/
public static boolean delete(Object obj) {
boolean flag = false;
Class<?> c = obj.getClass(); //獲取obj的Class
//構造刪除的SQL語句
StringBuffer sb = new StringBuffer("delete from ");
sb.append(c.getSimpleName()).append(" where ");
//獲取物件屬性陣列
Field[] field = c.getDeclaredFields();
//設定第一個屬性的可訪問性
field[0].setAccessible(true);
//獲取第一個屬性的屬性名構造刪除sql
sb.append(field[0].getName()).append("=?");
String sql = sb.toString();
Connection conn = getConnection();
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
ps.setObject(1, field[0].get(obj));
System.out.println(ps);
flag = ps.execute();
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}finally {
close(ps);
close(conn);
}
return flag;
}
2.3、修改
/**
* 模擬jdbc的更新操作,預設第一個屬性為主鍵
* @param obj
* @return
*/
public static boolean update(Object obj) {
boolean flag = false;
Class<?> c = obj.getClass();
StringBuffer sb = new StringBuffer("update "+ c.getSimpleName() +" set ");
Field[] field = c.getDeclaredFields();
for(int i = 1; i < field.length; i++) {
if(i != field.length-1) {
sb.append(field[i].getName()).append("=?,");
}else {
sb.append(field[i].getName()).append("=? where ");
}
}
sb.append(field[0].getName() + "=?");
String sql = sb.toString();
Connection conn = getConnection();
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
for(int i = 1; i < field.length; i++) {
field[i].setAccessible(true);
ps.setObject(i, field[i].get(obj));
}
field[0].setAccessible(true);
ps.setObject(field.length, field[0].get(obj));
System.out.println(ps);
flag = ps.execute();
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}finally {
close(ps);
close(conn);
}
return flag;
}
2.4、查詢,查詢操作不需要傳入一個物件,只需要一個類的Class就可以
/**
* 模擬框架,通過物件的Class獲取對應表中的所有記錄
* @param obj
* @return
*/
public static <T> List<T> selectAll(Class<T> c) {
String sql = "select * from "+ c.getSimpleName(); //通過反射獲取類名對應表名構造SQL語句
List<T> list = new ArrayList<T>(); //儲存查詢結果
Field[] field = c.getDeclaredFields(); //通過反射獲取所有屬性
Connection conn = getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
System.out.println(ps);
rs = ps.executeQuery(); //返回結果集
while(rs.next()) {
T obj = c.newInstance(); //通過反射構造一個T型別的例項
for(int i = 0; i < field.length; i++) { //
field[i].setAccessible(true); //設定屬性的可訪問性(可以訪問私有屬性)
field[i].set(obj, rs.getObject(field[i].getName())); //通過屬性名獲取結果集中的值賦值到例項物件中
}
list.add(obj); //將例項物件新增到list集合
}
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}finally {
close(rs);
close(ps);
close(conn);
}
return list;
}