首页 > 代码库 > 【转】JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法

【转】JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法

转自:http://www.cnblogs.com/ysw-go/

 

JDBC元数据

1)DatabaseMetaData

    /**
     * 了解即可:DatabaseMetaData是描述数据库的元数据对象
     * 可以由Connection得到
     */

具体的应用代码:

 1 @Test
 2     public void testDatabaseMetaData(){
 3         Connection connection=null;
 4         ResultSet resultSet=null;
 5         try {
 6             connection=JDBCTools.getConnection();
 7             DatabaseMetaData data=http://www.mamicode.com/connection.getMetaData();
 8             //1.可以得到数据库本身的一些基本的信息
 9             //得到数据库的版本号
10             int version=data.getDatabaseMajorVersion();
11             System.out.println(version);
12             //2.得到连接数据库的用户名
13             String user=data.getUserName();
14             System.out.println(user);
15             //3.得到MySQl中有哪些数据库
16             resultSet=data.getCatalogs();
17             while(resultSet.next()){
18                 System.out.println(resultSet.getString(1));
19             }
20         } catch (Exception e) {
21             e.printStackTrace();
22         }finally{
23             JDBCTools.release(resultSet, null, connection);
24         }
25     }

2)ResultSetMetaData

/**
     * ResultSetMetaData:描述结果集的元数据
     * 可以得到结果集中的基本信息:结果集中有哪些列,列名,列的别名等等;
     */

具体的代码应用:

 1 @Test
 2     public void testResultSetMetaData(){
 3         Connection connection=null;
 4         PreparedStatement preparedStatement=null;
 5         ResultSet resultSet=null;
 6         try {
 7             connection=JDBCTools.getConnection();
 8             String sql="select id,name,email,birth"+
 9             " from customers";
10             preparedStatement=connection.prepareStatement(sql);
11             resultSet=preparedStatement.executeQuery();
12             ResultSetMetaData rsmd=resultSet.getMetaData();
13             //得到列数
14             int columnCount=rsmd.getColumnCount();
15             System.out.println(columnCount);
16             for(int i=0;i<columnCount;i++){
17                 //得到列名
18                 String columnName=rsmd.getColumnName(i+1);
19                 //得到列的别名
20                 String columnLabel=rsmd.getColumnLabel(i+1);
21                 System.out.println(columnName+":"+columnLabel);        
22             }
23             
24         } catch (Exception e) {
25             e.printStackTrace();
26         }finally{
27             JDBCTools.release(resultSet, preparedStatement, connection);
28         }
29     }

我们的查询操作,对于不同的数据表examstudent和customers,会有不同的代码编写过程,利用反射和JDBC元数据可以编写通用的方法进行对不同数据表的查询。

在此之前我们是这样做的:

查询customers表中的字段以及字段值:

 1 public Customer getCustomer(String sql, Object... args) {
 2         Customer customer = null;
 3         Connection connection = null;
 4         PreparedStatement preparedStatement = null;
 5         ResultSet resultSet = null;
 6         try {
 7             connection = JDBCTools.getConnection();
 8             preparedStatement = connection.prepareStatement(sql);
 9             for (int i = 0; i < args.length; i++) {
10                 preparedStatement.setObject(i + 1, args[i]);
11             }
12             resultSet = preparedStatement.executeQuery();
13             if (resultSet.next()) {
14                 // student = new Student(resultSet.getInt(1),
15                 // resultSet.getInt(2),
16                 // resultSet.getString(3), resultSet.getString(4),
17                 // resultSet.getString(5), resultSet.getString(6),
18                 // resultSet.getInt(7));
19                 customer = new Customer();
20                 customer.setId(resultSet.getInt(1));
21                 customer.setName(resultSet.getString(2));
22                 customer.setEmail(resultSet.getString(3));
23                 customer.setBirth(resultSet.getDate(4));
24             }
25         } catch (Exception e) {
26             e.printStackTrace();
27         } finally {
28             JDBCTools.release(resultSet, preparedStatement, connection);
29         }
30         return customer;
31 
32     }

查询examstudent表中的字段以及字段值:

 1 public Student getStudent(String sql, Object... args) {
 2         Student student = null;
 3         Connection connection = null;
 4         PreparedStatement preparedStatement = null;
 5         ResultSet resultSet = null;
 6         try {
 7             connection = JDBCTools.getConnection();
 8             preparedStatement = connection.prepareStatement(sql);
 9             for (int i = 0; i < args.length; i++) {
10                 preparedStatement.setObject(i + 1, args[i]);
11             }
12             resultSet = preparedStatement.executeQuery();
13             if (resultSet.next()) {
14                 student = new Student(resultSet.getInt(1), resultSet.getInt(2),
15                         resultSet.getString(3), resultSet.getString(4),
16                         resultSet.getString(5), resultSet.getString(6),
17                         resultSet.getInt(7));
18             }
19         } catch (Exception e) {
20             e.printStackTrace();
21         } finally {
22             JDBCTools.release(resultSet, preparedStatement, connection);
23         }
24         return student;
25 
26     }

元数据:元数据就是描述数据的数据

可以看到两个操作有共同的步骤,不同的地方代码相似度也很高,于是我们就可以在此基础上编写一个通用的方法实现我们查询数据表的操作。

/**
     * ResultSetMetaData: 
     * 1).是描述ResultSet的元数据对象,即从中可以获取到 结果集中有多少列,列名是什么。。。
     * 2).如何使用呢? 1.得到ResultSetMetaData对象: 调用ResultSet的getMetaData()方法
     * 2.ResultSetMetaData有哪些好用的方法?
     * 
     * >int getColumnCount():SQL语句中包含哪些列 
     * >String getColumn(int column):获取指定列的别名,其中索引从1开始
     * 
     */

具体的代码实现:

 1 public <T> T get(Class<T> classz, String sql, Object... args) {
 2         T entity = null;
 3         Connection connection = null;
 4         PreparedStatement preparedStatement = null;
 5         ResultSet resultSet = null;
 6         try {
 7             connection = JDBCTools.getConnection();
 8             preparedStatement = connection.prepareStatement(sql);
 9             for (int i = 0; i < args.length; i++) {
10                 preparedStatement.setObject(i + 1, args[i]);
11             }
12             resultSet = preparedStatement.executeQuery();
13 
14             ResultSetMetaData rsmd = resultSet.getMetaData();
15             Map<String, Object> values = new HashMap<String, Object>();
16             if (resultSet.next()) {
17                 for (int i = 0; i < rsmd.getColumnCount(); i++) {
18                     String columnLabel = rsmd.getColumnLabel(i + 1);
19                     Object columnValue =http://www.mamicode.com/ resultSet.getObject(columnLabel);
20                     values.put(columnLabel, columnValue);
21                 }
22             }
23             if (values.size() > 0) {
24                 entity = classz.newInstance();
25                 for (Map.Entry<String, Object> entry : values.entrySet()) {
26                     String fieldName = entry.getKey();
27                     Object fieldValue =http://www.mamicode.com/ entry.getValue();
28                     ReflectionUtils
29                             .setFieldValue(entity, fieldName, fieldValue);
30                 }
31             }
32         } catch (Exception e) {
33             e.printStackTrace();
34         } finally {
35             JDBCTools.release(resultSet, preparedStatement, connection);
36         }
37         // 返回包含查询信息的实体类对象
38         return entity;
39     }

get方法的编写实现步骤:

/**
     * 1.先利用SQL进行查询,得到结果集
     * 2.利用反射创建实体类的对象:创建Student对象
     * 3.获取结果集的列的别名:idCard、studentName 
     * 4.再获取结果集的每一列的值,结合3得到一个Map,键是列的别名:值;列的值:{flowid:5,type=6,idCard:xxx...} 列的别名和我们实体类的属性字段名一致
     * 5.再利用反射为2的对应的属性赋值   属性:Map的键   属性值:Map的键值
     */

我们写一个@test方法测试一下:

 1     @Test
 2     public void testGet() {
 3         String sql = "select id,name,email,birth "
 4                 + " from customers where id=?";
 5         System.out.println(sql);
 6         Customer customer = get(Customer.class, sql, 3);
 7         System.out.println(customer);
 8         sql = "select  flow_id flowId,type, idcard idCard, exam_card examCard,"
 9                 + "student_name studentName,location,grade from examstudent where "
10                 + " flow_id=?";
11         System.out.println(sql);
12         Student student = get(Student.class, sql, 3);
13         System.out.println(student);
14     }

运行结果:

select id,name,email,birth  from customers where id=?
Customer [id=3, name=ABCD, email=mike@163.com, birth=1992-06-07]
select  flow_id flowId,type, idcard idCard, exam_card examCard,student_name studentName,location,grade from examstudent where  flow_id=?
Student [flowId=3, type=6, idCard=371522199206078411, examCard=2015534083, studentName=li, location=dalian, grade=87]

BeanUtils包的使用

BeanUtils工具包是由Apache公司所开发,主要是方便程序员对Bean类能够进行简便的操作。

在使用BeanUtils工具包之前我们需要的Jar包有以下几种:

(1)   BeanUtils相关包

commons-beanutils-1.8.3.jar

commons-beanutils-1.8.3-javadoc.jar

commons-beanutils-1.8.3-javadoc.jar

commons-beanutils-bean-collections-1.8.3.jar

commons-beanutils-core-1.8.3.jar

(2)   Logic4j相关包 

commons-logging.jar

log4j.jar

      既然要对Bean对象进行操作,那么就需要一个Bean的测试类,我们以下面为所测试的Bean类

 1 public class Student {
2
3
4
5 private String name;
6
7 private int age;
8
9 private Date birth;
10
11
12
13
14
15 public String getName() {
16
17 return name;
18
19 }
20
21 public void setName(String name) {
22
23 this.name = name;
24
25 }
26
27 public int getAge() {
28
29 return age;
30
31 }
32
33 public void setAge(int age) {
34
35 this.age = age;
36
37 }
38
39 public Date getBirth() {
40
41 return birth;
42
43 }
44
45 public void setBirth(Date birth) {
46
47 this.birth = birth;
48
49 }
50
51
52
53 }

一、先赋值Bean对象里的字段属性,然后再取值:

 1 @Test
2
3 public void test01() throws Exception{
4
5 //1.加载类
6  
7 Class clss = Class.forName("com.L.introspector.Student");
8
9 //2.创建Bean对象
10  
11 Student st = (Student) clss.newInstance();
12
13 //3.通过BeanUtils给对象属性赋值
14  
15 BeanUtils.setProperty(st, "name", "L。");
16
17 //4.输出对象属性值
18  
19 String str = BeanUtils.getProperty(st, "name");
20
21 System.out.println(str);
22
23 }

BeanUtils的setProperty(object,name,value)方法需要的参数分别是

Object=加载类的对象

Name=类属性的名称

Value=http://www.mamicode.com/所赋的值;

BeanUtils的getProperty(object,name)方法的返回值是String类型,所以可以直接输出;

因此我们的get方法中的代码:

ReflectionUtils.setFieldValue(entity, fieldName, fieldValue);可以更改为

BeanUtils.setProperty(entity, fieldName, fieldValue);

【转】JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法