求教!! java JBDC利用反射及JDBC元数据编写通用的查询方法

我使用是三个类  JDBCTools ,ReflectionUtils,JDBCTest

我调用JDBCTest中的  testResultSetMetaData() 查询Student 时一直发生 java.lang.IllegalArgumentException异常

用的是Oracle 数据库   下面是代码和截图  求教 实在想不出哪里出错了

下面代码分别是JDBCTest    ReflectionUtils    JDBCTools     Student   四个类 

http://img.mukewang.com/596435910001f0c412390504.jpg

http://img.mukewang.com/596435920001db4a13550709.jpg

数据库建立的表

create table examstudents4 (

flow_id number(3),

type_id number(3),

id_card varchar2(20),

exam_card  varchar2(20),

student_name varchar2(20),

location varchar2(20),

grade number(3)

)




连接数据库的配置文件   文件名字  jdbc.properties

driver=oracle.jdbc.driver.OracleDriver

jdbcUrl=jdbc:oracle:thin:@localhost:1521:orcl

user=scott

password=tiger





import static org.junit.Assert.*;


//import java.util.Properties;

//import java.util.Scanner;

//import java.io.File;

//import java.io.FileInputStream;

//import java.io.IOException;

//import java.io.InputStream;

//import java.sql.Connection;

//import java.sql.Driver;

//import java.sql.DriverManager;

//import java.sql.PreparedStatement;

//import java.sql.ResultSet;

//import java.sql.ResultSetMetaData;

//import java.sql.SQLException;

//import java.sql.Statement;

//import org.junit.Test;

//import java.util.*;

//import java.util.Map;;

import java.sql.Connection;

import java.sql.Date;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.Statement;

import java.util.HashMap;

import java.util.Map;

import java.util.Scanner;


import org.junit.Test;



public class JDBCTest1 {

@Test

public void testGet() {

String sql = "SELECT id, name, email, birth "

+ "FROM customers WHERE id = ?";

// System.out.println(sql);

//

// Customer customer = get(Customer.class, sql, 5);

// System.out.println(customer);


sql = "SELECT flow_id flowId, type_id type, id_card idCard, "

+ "exam_card examCard, student_name studentName, "

+ "location, grade " + "FROM examstudent3 WHERE flow_id = ?";

// System.out.println(sql);


Student stu = get(Student.class, sql, 1);

System.out.println(stu);

}


/**

* 通用的查询方法:可以根据传入的 SQL、Class 对象返回 SQL 对应的记录的对象

* @param clazz: 描述对象的类型

* @param sql: SQL 语句。可能带占位符

* @param args: 填充占位符的可变参数。

* @return

*/

public <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 = JDBCTools.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<String,Object>();


//4. 处理结果集. 利用 ResultSetMetaData 填充 3 对应的 Map 对象

if(resultSet.next()){

for(int i = 0; i < rsmd.getColumnCount(); i++){

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();

ReflectionUtils.setFieldValue(entity, fieldName, value);

}

}



} catch (Exception e) {

e.printStackTrace();

} finally {

JDBCTools.releaseDB(resultSet, preparedStatement, connection);

}


return entity;

}


@Test

public void testResultSetMetaData1() {

Connection connection = null;

PreparedStatement preparedStatement = null;

ResultSet resultSet = null;


try {

String sql = "SELECT flow_id flowId, type_id type, id_card idCard, "

+ "exam_card examCard, student_name studentName, "

+ "location location, grade grade " + "FROM examstudent3 WHERE flow_id = ?";


connection = JDBCTools.getConnection();

preparedStatement = connection.prepareStatement(sql);

preparedStatement.setInt(1, 1);


resultSet = preparedStatement.executeQuery();


Map<String, Object> values = 

new HashMap<String, Object>();


//1. 得到 ResultSetMetaData 对象

ResultSetMetaData rsmd = resultSet.getMetaData();


while(resultSet.next()){

//2. 打印每一列的列名

for(int i = 0; i < rsmd.getColumnCount(); i++){

String columnLabel = rsmd.getColumnLabel(i + 1);

Object columnValue = resultSet.getObject(columnLabel);


values.put(columnLabel, columnValue);

}

}


//System.out.println(values); 


Class clazz = Student.class;


Object object = clazz.newInstance();

for(Map.Entry<String, Object> entry: values.entrySet()){

String fieldName = entry.getKey();

Object fieldValue = entry.getValue();


// System.out.println(fieldName + ": " + fieldValue);


ReflectionUtils.setFieldValue(object, fieldName, fieldValue);

}


System.out.println(object); 



} catch (Exception e) {

e.printStackTrace();

} finally {

JDBCTools.releaseDB(resultSet, preparedStatement, connection);

}

}

}










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 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 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;

}

}







import java.io.IOException;

import java.io.InputStream;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.Properties;


public class JDBCTools {


/**

* 执行 SQL 语句, 使用 PreparedStatement

* @param sql

* @param args: 填写 SQL 占位符的可变参数

*/

public static void update(String sql, Object ... args){

Connection connection = null;

PreparedStatement preparedStatement = null;


try {

connection = JDBCTools.getConnection();

preparedStatement = connection.prepareStatement(sql);


for(int i = 0; i < args.length; i++){

preparedStatement.setObject(i + 1, args[i]);

}


preparedStatement.executeUpdate();


} catch (Exception e) {

e.printStackTrace();

} finally{

JDBCTools.releaseDB(null, preparedStatement, connection);

}

}


/**

* 执行 SQL 的方法

* @param sql: insert, update 或 delete。 而不包含 select

*/

public static void update(String sql) {

Connection connection = null;

Statement statement = null;


try {

// 1. 获取数据库连接

connection = getConnection();


// 2. 调用 Connection 对象的 createStatement() 方法获取 Statement 对象

statement = connection.createStatement();


// 4. 发送 SQL 语句: 调用 Statement 对象的 executeUpdate(sql) 方法

statement.executeUpdate(sql);


} catch (Exception e) {

e.printStackTrace();

} finally {

// 5. 关闭数据库资源: 由里向外关闭.

releaseDB(null, statement, connection);

}

}


/**

* 释放数据库资源的方法

* @param resultSet

* @param statement

* @param connection

*/

public static void releaseDB(ResultSet resultSet, Statement statement,

Connection connection) {


if (resultSet != null) {

try {

resultSet.close();

} catch (SQLException e) {

e.printStackTrace();

}

}


if (statement != null) {

try {

statement.close();

} catch (SQLException e) {

e.printStackTrace();

}

}


if (connection != null) {

try {

connection.close();

} catch (SQLException e) {

e.printStackTrace();

}

}


}


/**

* 获取数据库连接的方法

*/

public static Connection getConnection() throws IOException,

ClassNotFoundException, SQLException {

// 0. 读取 jdbc.properties

/**

* 1). 属性文件对应 Java 中的 Properties 类 2). 可以使用类加载器加载 bin 目录(类路径下)的文件

*/

Properties properties = new Properties();

InputStream inStream = JDBCTools.class.getClassLoader()

.getResourceAsStream("jdbc.properties");

properties.load(inStream);


// 1. 准备获取连接的 4 个字符串: user, password, jdbcUrl, driverClass

String user = properties.getProperty("user");

String password = properties.getProperty("password");

String jdbcUrl = properties.getProperty("jdbcUrl");

String driverClass = properties.getProperty("driver");


// 2. 加载驱动: Class.forName(driverClass)

Class.forName(driverClass);


// 3. 调用

// DriverManager.getConnection(jdbcUrl, user, password)

// 获取数据库连接

Connection connection = DriverManager.getConnection(jdbcUrl, user,

password);

return connection;

}


}









public class Student {


// 流水号

private int flowId;

// 考试的类型

private int type;

// 身份证号

private String idCard;

// 准考证号

private String examCard;

// 学生名

private String studentName;

// 学生地址

private String location;

// 考试分数.

private int grade;


public int getFlowId() {

return flowId;

}


public void setFlowId(int flowId) {

this.flowId = flowId;

}


public int getType() {

return type;

}


public void setType(int type) {

this.type = type;

}


public String getIdCard() {

return idCard;

}


public void setIdCard(String idCard) {

this.idCard = idCard;

}


public String getExamCard() {

return examCard;

}


public void setExamCard(String examCard) {

this.examCard = examCard;

}


public String getStudentName() {

return studentName;

}


public void setStudentName(String studentName) {

this.studentName = studentName;

}


public String getLocation() {

return location;

}


public void setLocation(String location) {

this.location = location;

}


public int getGrade() {

return grade;

}


public void setGrade(int grade) {

this.grade = grade;

}


public Student(int flowId, int type, String idCard, String examCard,

String studentName, String location, int grade) {

super();

this.flowId = flowId;

this.type = type;

this.idCard = idCard;

this.examCard = examCard;

this.studentName = studentName;

this.location = location;

this.grade = grade;

}


public Student() {

// TODO Auto-generated constructor stub

}


@Override

public String toString() {

return "Student [flowId=" + flowId + ", type=" + type + ", idCard="

+ idCard + ", examCard=" + examCard + ", studentName="

+ studentName + ", location=" + location + ", grade=" + grade

+ "]";

}


}


qq_阿篮_0
浏览 1945回答 3
3回答

YJjava

你哪里参数不合法,传参的时候注意,转型的地方注意。看报错可能是你查询的参数和你的数据库字段名没对上。

黄小凡

大哥,你觉得真的会有人去认真看你这么多源码吗?问也是白问。。。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java
Oracle