<form id="hz9zz"></form>
  • <form id="hz9zz"></form>

      <nobr id="hz9zz"></nobr>

      <form id="hz9zz"></form>

    1. 明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

      Jakarta-Common-BeanUtils研究心得(2)

      [摘要]允許隨意轉載,但請注明出處及作者。=========================================Jakarta-Common-BeanUtils研究心得(2)SonyMusic2...
      允許隨意轉載,但請注明出處及作者。

      =========================================

      Jakarta-Common-BeanUtils研究心得(2)
      SonyMusic
      2003.05.13

      六、ConstructorUtils補遺
      創建對象還有一個方法:invokeExactConstructor,該方法對參數要求
      更加嚴格,傳遞進去的參數必須嚴格符合構造方法的參數列表。
      例如:
      Object[] args={new Integer(1), "Jan"};
      Class[] argsType={int.class, String.class};
      Object obj;
      //下面這句調用將不會成功,因為args[0]的類型為Integer,而不是int
      //obj = ConstructorUtils.invokeExactConstructor(Month.class, args);

      //這一句就可以,因為argsType指定了類型。
      obj = ConstructorUtils.invokeExactConstructor(Month.class, args, argsType);
      Month month=(Month)obj;
      System.out.println(BeanUtils.getProperty(month,"value"));


      七、MethodUtils
      與ConstructorUtils類似,不過調用的時候,通常需要再指定一個method name的參數。

      八、DynaClass/DynaBean
      這似乎是BeanUtils中最有趣的部分之一了,很簡單,簡單到光看這兩個接口中的方法會不明白
      為什么要設計這兩個接口。不過看到ResultSetDynaClass后,就明白了。下面是java doc中的代碼:
       ResultSet rs = ...;
       ResultSetDynaClass rsdc = new ResultSetDynaClass(rs);
       Iterator rows = rsdc.iterator();
       while (rows.hasNext()){
       DynaBean row = (DynaBean) rows.next();
       ... process this row ...
       }
       rs.close();
      原來這是一個ResultSet的包裝器,ResultSetDynaClass實現了DynaClass,它的iterator方法返回一個
      ResultSetIterator,則是實現了DynaBean接口。
      在獲得一個DynaBean之后,我們就可以用
       DynaBean row = (DynaBean) rows.next();
       System.out.println(row.get("field1")); //field1是其中一個字段的名字

      再看另一個類RowSetDynaClass的用法,代碼如下:
      String driver="com.mysql.jdbc.Driver";
      String url="jdbc:mysql://localhost/2hu?useUnicode=true&characterEncoding=GBK";
      String username="root";
      String password="";

      java.sql.Connection con=null;
      PreparedStatement ps=null;
      ResultSet rs=null;
      try {
      Class.forName(driver).newInstance();
      con = DriverManager.getConnection(url);
      ps=con.prepareStatement("select * from forumlist");
      rs=ps.executeQuery();
      //先打印一下,用于檢驗后面的結果。
      while(rs.next()){
      System.out.println(rs.getString("name"));
      }
      rs.beforeFirst();//這里必須用beforeFirst,因為RowSetDynaClass只從當前位置向前滾動

      RowSetDynaClass rsdc = new RowSetDynaClass(rs);
      rs.close();
      ps.close();
      List rows = rsdc.getRows();//返回一個標準的List,存放的是DynaBean
      for (int i = 0; i <rows.size(); i++) {
      DynaBean b=(DynaBean)rows.get(i);
      System.out.println(b.get("name"));
      }
      } catch (Exception e) {
      e.printStackTrace();
      }
      finally{
      try {
      con.close();
      } catch (Exception e) {
      }
      }

      是不是很有趣?封裝了ResultSet的數據,代價是占用內存。如果一個表有10萬條記錄,rsdc.getRows()
      就會返回10萬個記錄。@_@

      需要注意的是ResultSetDynaClass和RowSetDynaClass的不同之處:
      1,ResultSetDynaClass是基于Iterator的,一次只返回一條記錄,而RowSetDynaClass是基于
      List的,一次性返回全部記錄。直接影響是在數據比較多時ResultSetDynaClass會比較的快速,
      而RowSetDynaClass需要將ResultSet中的全部數據都讀出來(并存儲在其內部),會占用過多的
      內存,并且速度也會比較慢。
      2,ResultSetDynaClass一次只處理一條記錄,在處理完成之前,ResultSet不可以關閉。
      3,ResultSetIterator的next()方法返回的DynaBean其實是指向其內部的一個固定
      對象,在每次next()之后,內部的值都會被改變。這樣做的目的是節約內存,如果你需要保存每
      次生成的DynaBean,就需要創建另一個DynaBean,并將數據復制過去,下面也是java doc中的代碼:
       ArrayList results = new ArrayList(); // To hold copied list
       ResultSetDynaClass rsdc = ...;
       DynaProperty properties[] = rsdc.getDynaProperties();
       BasicDynaClass bdc =
       new BasicDynaClass("foo", BasicDynaBean.class,
      rsdc.getDynaProperties());
       Iterator rows = rsdc.iterator();
       while (rows.hasNext()) {
       DynaBean oldRow = (DynaBean) rows.next();
       DynaBean newRow = bdc.newInstance();
       PropertyUtils.copyProperties(newRow, oldRow);
       results.add(newRow);
       }

      事實上DynaClass/DynaBean可以用于很多地方,存儲各種類型的數據。自己想吧。嘿嘿。


      九、自定義的CustomRowSetDynaClass
      兩年前寫過一個與RowSetDynaClass目標相同的類,不過多一個功能,就是分頁,只取需要的數據,
      這樣內存占用就會減少。

      先看一段代碼:
      String driver="com.mysql.jdbc.Driver";
      String url="jdbc:mysql://localhost/2hu?useUnicode=true&characterEncoding=GBK";
      String username="root";
      String password="";

      java.sql.Connection con=null;
      PreparedStatement ps=null;
      ResultSet rs=null;
      try {
      Class.forName(driver).newInstance();
      con = DriverManager.getConnection(url);
      ps=con.prepareStatement("select * from forumlist order by name");
      rs=ps.executeQuery();
      /*
      while(rs.next()){
      System.out.println(rs.getString("name"));
      }
      rs.beforeFirst();
      */

      //第二個參數表示第幾頁,第三個參數表示頁的大小
      CustomRowSetDynaClass rsdc = new CustomRowSetDynaClass(rs, 2, 5);
      //RowSetDynaClass rsdc = new RowSetDynaClass(rs);
      rs.close();
      ps.close();
      List rows = rsdc.getRows();
      for (int i = 0; i <rows.size(); i++) {
      DynaBean b=(DynaBean)rows.get(i);
      System.out.println(b.get("name"));
      }
      } catch (Exception e) {
      e.printStackTrace();
      }
      finally{
      try {
      con.close();
      } catch (Exception e) {
      }
      }
      在這里用到了一個CustomRowSetDynaClass類,構造方法中增加了page和pageSize兩個參數,
      這樣,不管數據庫里有多少條記錄,最多只取pageSize條記錄,若pageSize==-1,則功能和
      RowSetDynaClass一樣。這在大多數情況下是適用的。該類的代碼如下:

      package test.jakarta.commons.beanutils;

      import java.io.*;
      import java.sql.*;
      import java.util.*;

      import org.apache.commons.beanutils.*;

      /**
      * @author SonyMusic
      *
      * To change this generated comment edit the template variable "typecomment":
      * Window>Preferences>Java>Templates.
      * To enable and disable the creation of type comments go to
      * Window>Preferences>Java>Code Generation.
      */
      public class CustomRowSetDynaClass implements DynaClass, Serializable {

      // ----------------------------------------------------------- Constructors

      /**
      * <p>Construct a new {@link RowSetDynaClass} for the specified
      * <code>ResultSet</code>.The property names corresponding
      * to column names in the result set will be lower cased.</p>
      *
      * @param resultSet The result set to be wrapped
      *
      * @exception NullPointerException if <code>resultSet</code>
      *is <code>null</code>
      * @exception SQLException if the metadata for this result set
      *cannot be introspected
      */
      public CustomRowSetDynaClass(ResultSet resultSet) throws SQLException {

      this(resultSet, true);

      }

      /**
      * <p>Construct a new {@link RowSetDynaClass} for the specified
      * <code>ResultSet</code>.The property names corresponding
      * to the column names in the result set will be lower cased or not,
      * depending on the specified <code>lowerCase</code> value.</p>
      *
      * <p><strong>WARNING</strong> - If you specify <code>false</code>
      * for <code>lowerCase</code>, the returned property names will
      * exactly match the column names returned by your JDBC driver.
      * Because different drivers might return column names in different
      * cases, the property names seen by your application will vary
      * depending on which JDBC driver you are using.</p>
      *
      * @param resultSet The result set to be wrapped
      * @param lowerCase Should property names be lower cased?
      *
      * @exception NullPointerException if <code>resultSet</code>
      *is <code>null</code>
      * @exception SQLException if the metadata for this result set
      *cannot be introspected
      */
      public CustomRowSetDynaClass(ResultSet resultSet, boolean lowerCase)
      throws SQLException {

      this(resultSet, 1, -1, lowerCase);

      }

      public CustomRowSetDynaClass(
      ResultSet resultSet,
      int page,
      int pageSize,
      boolean lowerCase)
      throws SQLException {

      if (resultSet == null) {
      throw new NullPointerException();
      }
      this.lowerCase = lowerCase;
      this.page = page;
      this.pageSize = pageSize;

      introspect(resultSet);
      copy(resultSet);

      }

      public CustomRowSetDynaClass(ResultSet resultSet, int page, int pageSize)
      throws SQLException {
      this(resultSet, page, pageSize, true);
      }

      // ----------------------------------------------------- Instance Variables

      /**
      * <p>Flag defining whether column names should be lower cased when
      * converted to property names.</p>
      */
      protected boolean lowerCase = true;

      protected int page = 1;
      protected int pageSize = -1;

      /**
      * <p>The set of dynamic properties that are part of this
      * {@link DynaClass}.</p>
      */
      protected DynaProperty properties[] = null;

      /**
      * <p>The set of dynamic properties that are part of this
      * {@link DynaClass}, keyed by the property name.Individual descriptor
      * instances will be the same instances as those in the
      * <code>properties</code> list.</p>
      */
      protected Map propertiesMap = new HashMap();

      /**
      * <p>The list of {@link DynaBean}s representing the contents of
      * the original <code>ResultSet</code> on which this
      * {@link RowSetDynaClass} was based.</p>
      */
      protected List rows = new ArrayList();

      // ------------------------------------------------------ DynaClass Methods

      /**
      * <p>Return the name of this DynaClass (analogous to the
      * <code>getName()</code> method of <code>java.lang.Class</code), which
      * allows the same <code>DynaClass</code> implementation class to support
      * different dynamic classes, with different sets of properties.</p>
      */
      public String getName() {

      return (this.getClass().getName());

      }

      /**
      * <p>Return a property descriptor for the specified property, if it
      * exists; otherwise, return <code>null</code>.</p>
      *
      * @param name Name of the dynamic property for which a descriptor
      *is requested
      *
      * @exception IllegalArgumentException if no property name is specified
      */
      public DynaProperty getDynaProperty(String name) {

      if (name == null) {
      throw new IllegalArgumentException("No property name specified");
      }
      return ((DynaProperty) propertiesMap.get(name));

      }

      /**
      * <p>Return an array of <code>ProperyDescriptors</code> for the properties
      * currently defined in this DynaClass.If no properties are defined, a
      * zero-length array will be returned.</p>
      */
      public DynaProperty[] getDynaProperties() {

      return (properties);

      }

      /**
      * <p>Instantiate and return a new DynaBean instance, associated
      * with this DynaClass.<strong>NOTE</strong> - This operation is not
      * supported, and throws an exception.</p>
      *
      * @exception IllegalAccessException if the Class or the appropriate
      *constructor is not accessible
      * @exception InstantiationException if this Class represents an abstract
      *class, an array class, a primitive type, or void; or if instantiation
      *fails for some other reason
      */
      public DynaBean newInstance()
      throws IllegalAccessException, InstantiationException {

      throw new UnsupportedOperationException("newInstance() not supported");

      }

      // --------------------------------------------------------- Public Methods

      /**
      * <p>Return a <code>List</code> containing the {@link DynaBean}s that
      * represent the contents of each <code>Row</code> from the
      * <code>ResultSet</code> that was the basis of this
      * {@link RowSetDynaClass} instance.These {@link DynaBean}s are
      * disconnected from the database itself, so there is no problem with
      * modifying the contents of the list, or the values of the properties
      * of these {@link DynaBean}s.However, it is the application's
      * responsibility to persist any such changes back to the database,
      * if it so desires.</p>
      */
      public List getRows() {

      return (this.rows);

      }

      // ------------------------------------------------------ Protected Methods

      /**
      * <p>Copy the column values for each row in the specified
      * <code>ResultSet</code> into a newly created {@link DynaBean}, and add
      * this bean to the list of {@link DynaBean}s that will later by
      * returned by a call to <code>getRows()</code>.</p>
      *
      * @param resultSet The <code>ResultSet</code> whose data is to be
      *copied
      *
      * @exception SQLException if an error is encountered copying the data
      */
      protected void copy(ResultSet resultSet) throws SQLException {
      int abs = 0;
      int rowsCount = 0;
      int currentPageRows = 0;
      resultSet.last();
      rowsCount = resultSet.getRow();
      if (pageSize != -1) {
      int totalPages = (int) Math.ceil(((double) rowsCount) / pageSize);
      if (page > totalPages)
      page = totalPages;
      if (page < 1)
      page = 1;
      abs = (page - 1) * pageSize;

      //currentPageRows=(page==totalPages?rowsCount-pageSize*(totalPages-1):pageSize);
      } else
      pageSize = rowsCount;
      if (abs == 0)
      resultSet.beforeFirst();
      else
      resultSet.absolute(abs);
      //int
      while (resultSet.next() && ++currentPageRows <= pageSize) {
      DynaBean bean = new BasicDynaBean(this);
      for (int i = 0; i < properties.length; i++) {
      String name = properties[i].getName();
      bean.set(name, resultSet.getObject(name));
      }
      rows.add(bean);
      }

      }

      /**
      * <p>Introspect the metadata associated with our result set, and populate
      * the <code>properties</code> and <code>propertiesMap</code> instance
      * variables.</p>
      *
      * @param resultSet The <code>resultSet</code> whose metadata is to
      *be introspected
      *
      * @exception SQLException if an error is encountered processing the
      *result set metadata
      */
      protected void introspect(ResultSet resultSet) throws SQLException {

      // Accumulate an ordered list of DynaProperties
      ArrayList list = new ArrayList();
      ResultSetMetaData metadata = resultSet.getMetaData();
      int n = metadata.getColumnCount();
      for (int i = 1; i <= n; i++) { // JDBC is one-relative!
      DynaProperty dynaProperty = createDynaProperty(metadata, i);
      if (dynaProperty != null) {
      list.add(dynaProperty);
      }
      }

      // Convert this list into the internal data structures we need
      properties =
      (DynaProperty[]) list.toArray(new DynaProperty[list.size()]);
      for (int i = 0; i < properties.length; i++) {
      propertiesMap.put(properties[i].getName(), properties[i]);
      }

      }

      /**
      * <p>Factory method to create a new DynaProperty for the given index
      * into the result set metadata.</p>
      *
      * @param metadata is the result set metadata
      * @param i is the column index in the metadata
      * @return the newly created DynaProperty instance
      */
      protected DynaProperty createDynaProperty(
      ResultSetMetaData metadata,
      int i)
      throws SQLException {

      String name = null;
      if (lowerCase) {
      name = metadata.getColumnName(i).toLowerCase();
      } else {
      name = metadata.getColumnName(i);
      }
      String className = null;
      try {
      className = metadata.getColumnClassName(i);
      } catch (SQLException e) {
      // this is a patch for HsqlDb to ignore exceptions
      // thrown by its metadata implementation
      }

      // Default to Object type if no class name could be retrieved
      // from the metadata
      Class clazz = Object.class;
      if (className != null) {
      clazz = loadClass(className);
      }
      return new DynaProperty(name, clazz);

      }

      /**
      * <p>Loads and returns the <code>Class</code> of the given name.
      * By default, a load from the thread context class loader is attempted.
      * If there is no such class loader, the class loader used to load this
      * class will be utilized.</p>
      *
      * @exception SQLException if an exception was thrown trying to load
      *the specified class
      */
      protected Class loadClass(String className) throws SQLException {

      try {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      if (cl == null) {
      cl = this.getClass().getClassLoader();
      }
      return (cl.loadClass(className));
      } catch (Exception e) {
      throw new SQLException(
      "Cannot load column class '" + className + "': " + e);
      }

      }

      }

      大部分代碼從BeanUtils的源碼中取得,只做了簡單的修改,沒有加多余的注釋。如果要正式使用,
      需要再做精加工。

      ========================================
      關于這個包,只準備測試到這里了,不過已經有了大概的印象了,至少,知道這個包可以做些什么。
      其實這個筆記也只是起到這個作用。@_@




      日韩精品一区二区三区高清