利用反射及JDBC元數據編寫通用的查詢方法
遇到了若干問題:
1.從oracle返回的列名都是大寫,再用反射,就找不到相對應得 名字
2.oracle 中number類型 返回來,就變成了BigDecimal
public static void main(String[] args){
String sql = "SELECT IDCARD , examcard , "
+ "studentname ,"
+ "lacation LoCATION,grade "
+ " FROM student WHERE IDCARD = ?";
Student s = get(Student.class, sql, 7);
System.out.println(s);
}
//String sql = "SELECT id, name, email, birth "
<span style="white-space:pre"> </span>//<span style="white-space:pre"> </span>+ "FROM customers WHERE id = ?";
public static <T> T get(Class<T> clazz, String sql, Object... args) {
T entity = null;
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//1. 得到 ResultSet 對象
connection = JDBC_Tools.getConnection();
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
resultSet = preparedStatement.executeQuery();
//2. 得到 ResultSetMetaData 對象
ResultSetMetaData rsmd = resultSet.getMetaData();
//3. 創建一個 Map<String, Object> 對象, 鍵: SQL 查詢的列的別名,
//值: 列的值
Map<String, Object> values = new HashMap<>();
//4. 處理結果集. 利用 ResultSetMetaData 填充 3 對應的 Map 對象
if(resultSet.next()){
for(int i = 0; i < rsmd.getColumnCount(); i++){
//從 ResultSetMetaData 獲取列的別名
String columnLabel = rsmd.getColumnLabel(i + 1);
//從 結果集 中獲取列的值
Object columnValue = resultSet.getObject(i + 1);
values.put(columnLabel, columnValue);
}
}
//5. 若 Map 不為空集, 利用反射創建 clazz 對應的對象
if(values.size() > 0){
entity = clazz.newInstance();
//5. 遍歷 Map 對象, 利用反射為 Class 對象的對應的屬性賦值.
for(Map.Entry<String, Object> entry: values.entrySet()){
String fieldName = entry.getKey();
Object value = entry.getValue();
//System.out.println(fieldName+":"+value);
ReflectionUtils.setFieldValue(entity, fieldName, value); //出問題
//System.out.println(ReflectionUtils.getDeclaredField(entity,fieldName));
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBC_Tools.relaseSource(resultSet, connection, preparedStatement);
}
return entity;
}
} </pre>
ReflectionUtils.setFieldValue(entity, fieldName, value);出問題
java.lang.IllegalArgumentException: Can not set int field xuezaipiao3.Student.GRADE to java.math.BigDecimal
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeIntegerFieldAccessorImpl.set(UnsafeIntegerFieldAccessorImpl.java:98)
at java.lang.reflect.Field.set(Field.java:741)
at xuezaipiao3.ReflectionUtils.setFieldValue(ReflectionUtils.java:156)
at xuezaipiao3.ThinkInJDBC.get(ThinkInJDBC.java:77)
at xuezaipiao3.ThinkInJDBC.main(ThinkInJDBC.java:45)
Student [IDCARD=0, EXAMCARD=0, STUDENTNAME=null, LOCATION=7, GRADE=0]
Oracle 中 number類型 通過ResultSet 的 getObject() 返回的是 BigDecimal ,無法強制轉化,而且 ResultSetMetaData 的 getColumnLabel() 取回的 列的別名是大寫
MySQL不存在這樣的問題
用的 Oracle 10g
ReflectionUtils
package xuezaipiao3;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* 反射的 Utils 函數集合
* 提供訪問私有變量, 獲取泛型類型 Class, 提取集合中元素屬性等 Utils 函數
* @author Administrator
*
*/
public class ReflectionUtils {
/**
* 通過反射, 獲得定義 Class 時聲明的父類的泛型參數的類型
* 如: public EmployeeDao extends BaseDao<Employee, String>
* @param <T>
* @param clazz
* @param index
* @return
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(Class clazz, int index){
Type genType = clazz.getGenericSuperclass();
if(!(genType instanceof ParameterizedType)){
return Object.class;
}
Type [] params = ((ParameterizedType)genType).getActualTypeArguments();
if(index >= params.length || index < 0){
return Object.class;
}
if(!(params[index] instanceof Class)){
return Object.class;
}
return (Class) params[index];
}
/**
* 通過反射, 獲得 Class 定義中聲明的父類的泛型參數類型
* 如: public EmployeeDao extends BaseDao<Employee, String>
* @param <T>
* @param clazz
* @return
*/
@SuppressWarnings("unchecked")
public static<T> Class<T> getSuperGenericType(Class<T> clazz){
return getSuperClassGenricType(clazz, 0);
}
/**
* 循環向上轉型, 獲取對象的 DeclaredMethod
* @param object
* @param methodName
* @param parameterTypes
* @return
*/
public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes){
for(Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){
try {
//superClass.getMethod(methodName, parameterTypes);
return superClass.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
//Method 不在當前類定義, 繼續向上轉型
}
//..
}
return null;
}
/**
* 使 filed 變為可訪問
* @param field
*/
public static void makeAccessible(Field field){
if(!Modifier.isPublic(field.getModifiers())){
field.setAccessible(true);
}
}
/**
* 循環向上轉型, 獲取對象的 DeclaredField
* @param object
* @param filedName
* @return
*/
public static Field getDeclaredField(Object object, String filedName){
for(Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){
try {
return superClass.getDeclaredField(filedName);
} catch (NoSuchFieldException e) {
//Field 不在當前類定義, 繼續向上轉型
}
}
return null;
}
/**
* 直接調用對象方法, 而忽略修飾符(private, protected)
* @param object
* @param methodName
* @param parameterTypes
* @param parameters
* @return
* @throws InvocationTargetException
* @throws IllegalArgumentException
*/
public static Object invokeMethod(Object object, String methodName, Class<?> [] parameterTypes,
Object [] parameters) throws InvocationTargetException{
Method method = getDeclaredMethod(object, methodName, parameterTypes);
if(method == null){
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
}
method.setAccessible(true);
try {
return method.invoke(object, parameters);
} catch(IllegalAccessException e) {
System.out.println("不可能拋出的異常");
}
return null;
}
/**
* 直接設置對象屬性值, 忽略 private/protected 修飾符, 也不經過 setter
* @param object
* @param fieldName
* @param value
*/
public static void setFieldValue(Object object, String fieldName, Object value){
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
makeAccessible(field);
try {
field.set(object, value);
} catch (IllegalAccessException e) {
System.out.println("不可能拋出的異常");
}
}
/**
* 直接讀取對象的屬性值, 忽略 private/protected 修飾符, 也不經過 getter
* @param object
* @param fieldName
* @return
*/
public static Object getFieldValue(Object object, String fieldName){
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
makeAccessible(field);
Object result = null;
try {
result = field.get(object);
} catch (IllegalAccessException e) {
System.out.println("不可能拋出的異常");
}
return result;
}
} </pre>