上一篇介绍了PropertyUtils的用法,PropertyUtils主要是在不修改bean结构的前提下,动态访问bean的属性;
但是有时候,我们会经常希望能够在不定义一个Java类的前提下,动态决定这个类中包含哪些属性,并动态访问它们的属性值,比较典型的使用场景是作为SQL查询的结果集的bean;
为了支持以上特性,Apache Commons Beanutils包为我们提供了DynaBean接口、DynaClass接口;
举个简单例子如下:
DynaProperty[] props = new DynaProperty[]{ new DynaProperty("address", java.util.Map.class), new DynaProperty("subordinate", mypackage.Employee[].class), new DynaProperty("firstName", String.class), new DynaProperty("lastName", String.class) }; BasicDynaClass dynaClass = new BasicDynaClass("employee", null, props); DynaBean employee = dynaClass.newInstance(); employee.set("address", new HashMap()); employee.set("subordinate", new Employee[]{...}); employee.set("firstName", "Fred"); employee.set("lastName", "Flintstone"); DynaBean employee = ...; // 具体的DynaBean实现类 String firstName = (String) employee.get("firstName"); Address homeAddress = (Address) employee.get("address", "home"); Object subordinate = employee.get("subordinate", 2);
由于DynaBean和DynaClass都是接口,它们可以有多种实现形式,应用于多种场景。
接下来,会介绍在Apache Commons Beanutils包下,DynaBean和DynaClass接口不同的实现类;
当然,我们也可以自定义实现类来满足我们特定的需求;
基础实现类:BasicDynaBean和BasicDynaClass
先了解下这两个重要的实现,这两个类为DynaBean和DynaClass接口的基础实现类;
首先,我们可以这样创建一个DynaClass实例,其中类的成员属性是用DynaProperty类来描述的:
DynaProperty[] props = new DynaProperty[] { new DynaProperty("address", java.util.Map.class), new DynaProperty("subordinate", Employee[].class), new DynaProperty("firstName", String.class), new DynaProperty("lastName", String.class) }; BasicDynaClass dynaClass = new BasicDynaClass("employee", null, props);
注意这里的Class<?> dynaBeanClass参数为空,看下源码就发现,如果为null的话,默认会使用BasicDynaBean.class;
有了BasicDynaClass实例后,我们就可以开始创建DynaBean实例了,并且可以调用DynaBean接口中定义的方法,如get和set来读写属性值,如下所示:
DynaBean employee = dynaClass.newInstance(); employee.set("address", new HashMap<String, Object>()); employee.set("subordinate", new Employee[0]); employee.set("firstName", "Fred"); employee.set("lastName", "Flintstone");
System.out.println(employee.get("firstName"));
实现类:ResultSetDynaClass,处理数据库查询结果集
ResultSetDynaClass主要用于包装java.sql.ResultSet,即SQL查询时候返回的结果集;
不使用DynaBean的话,通常我们是这样处理的:
String sql = "SELECT id, name, address, state FROM user"; stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { Long id = rs.getLong("id"); String name = rs.getString("name"); String address = rs.getString("address"); boolean state = rs.getBoolean("state"); System.out.print("id: " + id); System.out.print(", name: " + name); System.out.print(", address: " + address); System.out.println(", state: " + state); }
使用ResultSetDynaClass的话,我们可以这样做:
String sql = "SELECT id, name, address, state FROM user"; stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery(sql); Iterator<DynaBean> rows = (new ResultSetDynaClass(rs)).iterator(); while (rows.hasNext()) { DynaBean row = rows.next(); System.out.print("id: " + row.get("id")); System.out.print(", name: " + row.get("name")); System.out.print(", address: " + row.get("address")); System.out.println(", state: " + row.get("state")); }
完整示例:
/* * File Name: ResultSetDyna.java * Description: * Author: PiChen * Create Date: 2017年5月30日 */ package apache.commons.beanutils.example.dynabeans; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Iterator; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.beanutils.ResultSetDynaClass; /** * * @author PiChen * @version 2017年5月30日 */ public class ResultSetDyna { static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost/demo"; static final String USER = "root"; static final String PASS = "root"; public static void main(String[] args) { Connection conn = null; PreparedStatement stmt = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection(DB_URL, USER, PASS); String sql = "SELECT id, name, address, state FROM user"; stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery(sql); // while (rs.next()) // { // Long id = rs.getLong("id"); // String name = rs.getString("name"); // String address = rs.getString("address"); // boolean state = rs.getBoolean("state"); // // System.out.print("id: " + id); // System.out.print(", name: " + name); // System.out.print(", address: " + address); // System.out.println(", state: " + state); // } Iterator<DynaBean> rows = (new ResultSetDynaClass(rs)).iterator(); while (rows.hasNext()) { DynaBean row = rows.next(); System.out.print("id: " + row.get("id")); System.out.print(", name: " + row.get("name")); System.out.print(", address: " + row.get("address")); System.out.println(", state: " + row.get("state")); } rs.close(); stmt.close(); conn.close(); } catch (SQLException se) { se.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (stmt != null) stmt.close(); } catch (SQLException se2) { } try { if (conn != null) conn.close(); } catch (SQLException se) { se.printStackTrace(); } } } }