<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    OMG,到底在尋找什么..................
    (構造一個完美的J2EE系統所需要的完整知識體系)
    posts - 198,  comments - 37,  trackbacks - 0
    ? BeanUtils:?威力和代價(轉載綜合)
    ?

    Apache Jakarta Commons項目非常有用。我曾在許多不同的項目上或直接或間接地使用各種流行的commons組件。其中的一個強大的組件就是BeanUtils。我將說明如何使用BeanUtils將local實體bean轉換為對應的value 對象:


    BeanUtils.copyProperties(aValue, aLocal)

    上面的代碼從aLocal對象復制屬性到aValue對象。它相當簡單!它不管local(或對應的value)對象有多少個屬性,只管進行復制。我們假設local對象有100個屬性。上面的代碼使我們可以無需鍵入至少100行的冗長、容易出錯和反復的get和set方法調用。這太棒了!太強大了!太有用了!

    現在,還有一個壞消息:使用BeanUtils的成本驚人地昂貴!我做了一個簡單的測試,BeanUtils所花費的時間要超過取數據、將其復制到對應的value對象(通過手動調用get和set方法),以及通過串行化將其返回到遠程的客戶機的時間總和。所以要小心使用這種威力!

    • 如果您有BeanUtils和類似的實用程序方面的體驗,請與我交流分享。
      +prakash

    Beanutils用了魔術般的反射技術,實現了很多夸張有用的功能,都是C/C++時代不敢想的。無論誰的項目,始終一天都會用得上它。我算是后知后覺了,第一回看到它的時候居然錯過。

    1.屬性的動態getter,setter

    在這框架滿天飛的年代,不能事事都保證執行getter,setter函數了,有時候屬性是要需要根據名字動態取得的,就像這樣:  
    BeanUtils.getProperty(myBean,"code");
    而BeanUtils更強的功能是直接訪問內嵌對象的屬性,只要使用點號分隔。
    BeanUtils.getProperty(orderBean, "address.city");
    相比之下其他類庫的BeanUtils通常都很簡單,不能訪問內嵌的對象,所以經常要用Commons BeanUtils替換它們。
    BeanUtils還支持List和Map類型的屬性。如下面的語法即可取得顧客列表中第一個顧客的名字
    BeanUtils.getProperty(orderBean, "customers[1].name");
    其中BeanUtils會使用ConvertUtils類把字符串轉為Bean屬性的真正類型,方便從HttpServletRequest等對象中提取bean,或者把bean輸出到頁面。
    而PropertyUtils就會原色的保留Bean原來的類型。

    2.beanCompartor 動態排序

    還是通過反射,動態設定Bean按照哪個屬性來排序,而不再需要在bean的Compare接口進行復雜的條件判斷。
    List peoples = ...; // Person對象的列表
    Collections.sort(peoples, new BeanComparator("age"));
    

    如果要支持多個屬性的復合排序,如"Order By lastName,firstName"

    ArrayList sortFields = new ArrayList();
    sortFields.add(new BeanComparator("lastName"));
    sortFields.add(new BeanComparator("firstName"));
    ComparatorChain multiSort = new ComparatorChain(sortFields);
    Collections.sort(rows,multiSort);
    

    其中ComparatorChain屬于jakata commons-collections包。
    如果age屬性不是普通類型,構造函數需要再傳入一個comparator對象為age變量排序。
    另外, BeanCompartor本身的ComparebleComparator, 遇到屬性為null就會拋出異常, 也不能設定升序還是降序。
    這個時候又要借助commons-collections包的ComparatorUtils.

    ?? Comparator mycmp = ComparableComparator.getInstance();
    ???mycmp = ComparatorUtils.nullLowComparator(mycmp);? //允許null
    ?? mycmp = ComparatorUtils.reversedComparator(mycmp); //逆序
    ?? Comparator cmp = new BeanComparator(sortColumn, mycmp);

    3.Converter 把Request或ResultSet中的字符串綁定到對象的屬性

    ?? 經常要從request,resultSet等對象取出值來賦入bean中,下面的代碼誰都寫膩了,如果不用MVC框架的綁定功能的話。

       String a = request.getParameter("a");
       bean.setA(a);
       String b = ....
    

    不妨寫一個Binder:

         MyBean bean = ...;
        HashMap map = new HashMap();
        Enumeration names = request.getParameterNames();
        while (names.hasMoreElements())
        {
          String name = (String) names.nextElement();
          map.put(name, request.getParameterValues(name));
        }
        BeanUtils.populate(bean, map);

    ??? 其中BeanUtils的populate方法或者getProperty,setProperty方法其實都會調用convert進行轉換。
    ????但Converter只支持一些基本的類型,甚至連java.util.Date類型也不支持。而且它比較笨的一個地方是當遇到不認識的類型時,居然會拋出異常來。
    ??? 對于Date類型,我參考它的sqldate類型實現了一個Converter,而且添加了一個設置日期格式的函數。
    要把這個Converter注冊,需要如下語句:

        ConvertUtilsBean convertUtils = new ConvertUtilsBean();
    ?? DateConverter dateConverter = new DateConverter();
    ?? convertUtils.register(dateConverter,Date.class);



    //因為要注冊converter,所以不能再使用BeanUtils的靜態方法了,必須創建BeanUtilsBean實例
    BeanUtilsBean beanUtils = new BeanUtilsBean(convertUtils,new PropertyUtilsBean());
    beanUtils.setProperty(bean, name, value);

    4 其他功能

    4.1 PropertyUtils,當屬性為Collection,Map時的動態讀取:
    ?
    Collection: 提供index
    ?? BeanUtils.getIndexedProperty(orderBean,"items",1);
    或者
    ? BeanUtils.getIndexedProperty(orderBean,"items[1]");

    Map: 提供Key Value
    ? BeanUtils.getMappedProperty(orderBean, "items","111");//key-value goods_no=111
    或者
    ? BeanUtils.getMappedProperty(orderBean, "items(111)")
    ?
    4.2 PropertyUtils,獲取屬性的Class類型
    ???? public static Class getPropertyType(Object bean, String name)
    ?
    4.3 ConstructorUtils,動態創建對象
    ????? public static Object invokeConstructor(Class klass, Object arg)
    4.4 MethodUtils,動態調用方法
        MethodUtils.invokeMethod(bean, methodName, parameter);
    4.5 動態Bean 用DynaBean減除不必要的VO和FormBean?
    一、概述
    第一次看到BeanUtils包,是在Struts項目中,作為Struts一個工具來使用的,
    估計功能越弄越強,就移到Common項目中了吧。

    BeanUtils一共有四個package:
    org.apache.commons.beanutils
    org.apache.commons.beanutils.converters
    org.apache.commons.beanutils.locale
    org.apache.commons.beanutils.locale.converters
    后三個包主要是用于數據的轉換,圍繞著一個Converter接口,該接口只有一個方法:
    java.lang.Object convert(java.lang.Class type, java.lang.Object value) ,
    用于將一個value轉換成另一個類型為type的Object。在一些自動化的應用中應該會有用。
    這里不作評論,以后有興趣了,或者覺得有用了,再行研究。
    這里只講第一個包。

    二、測試用的Bean
    在開始所有的測試之前,我寫了一個簡單的Bean,以便于測試,代碼如下:
    package test.jakarta.commons.beanutils;

    /**
    ?* @author SonyMusic
    ?*
    ?*/
    public class Month {
    ?private int value;
    ?private String name;
    ?private int[] days={11,22,33,44,55};

    ?public Month(int v, String n){
    ? ?value=v;
    ? ?name=n;
    ?}
    ?
    ?/**
    ? * Returns the name.
    ? * @return String
    ? */
    ?public String getName() {
    ? ?return name;
    ?}

    ?/**
    ? * Returns the value.
    ? * @return int
    ? */
    ?public int getValue() {
    ? ?return value;
    ?}

    ?/**
    ? * Sets the name.
    ? * @param name The name to set
    ? */
    ?public void setName(String name) {
    ? ?this.name = name;
    ?}

    ?/**
    ? * Sets the value.
    ? * @param value The value to set
    ? */
    ?public void setValue(int value) {
    ? ?this.value = value;
    ?}

    ?/**
    ? * @see java.lang.Object#toString()
    ? */
    ?public String toString() {
    ? ?return value+"("+name+")";
    ?}

    ?public int[] getDays() {
    ? ?return days;
    ?}

    ?public void setDays(int[] is) {
    ? ?days = is;
    ?}

    }

    三、BeanUtils
    這是一個主要應用于Bean的Util(呵呵,這個解釋很絕吧),以下是其中幾個方法的例子

    //static java.util.Map describe(java.lang.Object bean)
    //這個方法返回一個Object中所有的可讀屬性,并將屬性名/屬性值放入一個Map中,另外還有
    //一個名為class的屬性,屬性值是Object的類名,事實上class是java.lang.Object的一個屬性
    ?Month month=new Month(1, "Jan");
    ?
    ?try {
    ? ?Map map=BeanUtils.describe(month);
    ? ?Set keySet=map.keySet();
    ? ?for (Iterator iter = keySet.iterator(); iter.hasNext();) {
    ? ? ?Object element = (Object) iter.next();
    ? ? ?System.out.println("KeyClass:"+element.getClass().getName());
    ? ? ?System.out.println("ValueClass:"+map.get(element).getClass().getName());
    ? ? ?System.out.print(element+"\t");
    ? ? ?System.out.print(map.get(element));
    ? ? ?System.out.println();
    ? ?}
    ?} catch (IllegalAccessException e) {
    ? ?e.printStackTrace();
    ?} catch (InvocationTargetException e) {
    ? ?e.printStackTrace();
    ?} catch (NoSuchMethodException e) {
    ? ?e.printStackTrace();
    ?}
    輸出為:
    KeyClass:java.lang.String
    ValueClass:java.lang.String
    value ?1
    KeyClass:java.lang.String
    ValueClass:java.lang.String
    class ?class test.jakarta.commons.beanutils.Month
    KeyClass:java.lang.String
    ValueClass:java.lang.String
    name ?Jan
    注意到所有Map中的key/value都是String,而不管object中實際的值是多少。
    與此對應的還有static void populate(java.lang.Object bean, java.util.Map properties)
    用于將剛才describe出的Map再裝配成一個對象。


    再看這樣一段代碼
    曹曉鋼也許還記得,為了取一個不確定對象的property,著實花了不少時間,
    難度不大,但要做到100%的正確,仍然需要付出很大的精力。
    //static java.lang.String getProperty(java.lang.Object bean, java.lang.String name)
    ?Month month=new Month(1, "Jan");
    ?
    ?try {
    ? ?System.out.println(BeanUtils.getProperty(month,"value"));
    ?} catch (Exception e) {
    ? ?e.printStackTrace();
    ?}
    //輸出是:1

    與getProperty類似的還有getIndexedProperty, getMappedProperty,
    以getIndexedProperty為例:
    ?Month month=new Month(1, "Jan");
    ?
    ?try {
    ? ?System.out.println(BeanUtils.getIndexedProperty(month,"days",1));
    ? ?System.out.println(BeanUtils.getIndexedProperty(month,"days[1]"));
    ?} catch (Exception e) {
    ? ?e.printStackTrace();
    ?}
    這兩個調用是相同的。


    BeanUtils中還有一個方法:
    static void copyProperties(java.lang.Object dest, java.lang.Object orig)
    它真是太有用,還記得struts中滿天飛的都是copyProperties,我甚至懷疑整個BeanUtils最初
    是不是因為這個方法的需求才寫出來的。
    它將對象orig中的屬性復制到dest中去。


    四、PropertyUtils
    這個類和BeanUtils類很多的方法在參數上都是相同的,但返回值不同。
    BeanUtils著重于"Bean",返回值通常是String,而PropertyUtils著重于屬性,
    它的返回值通常是Object。


    五、ConstructorUtils
    這個類中的方法主要分成兩種,一種是得到構造方法,一種是創建對象。
    事實上多數時候得到構造方法的目的就是創建對象,這里只介紹一下創建對象。
    //static java.lang.Object ConstructorUtils.invokeConstructor
    //(java.lang.Class klass, java.lang.Object[] args)
    //根據一個java.lang.Class以及相應的構造方法的參數,創建一個對象。
    ?Object obj=ConstructorUtils.invokeConstructor(Month.class, {new Integer(1), "Jan"});
    ?Month month=(Month)obj;
    ?try {
    ? ?System.out.println(BeanUtils.getProperty(month,"value"));
    ?} catch (Exception e) {
    ? ?e.printStackTrace();
    ?}
    輸出證明,構造方法的調用是成功的。
    如果需要強制指定構造方法的參數類型,可以這樣調用:
    ? ?Object[] args={new Integer(1), "Jan"};
    ? ?Class[] argsType={int.class, String.class};
    ? ?Object obj;
    ? ?obj = ConstructorUtils.invokeExactConstructor(Month.class, args, argsType);
    ? ?Month month=(Month)obj;
    ? ?System.out.println(BeanUtils.getProperty(month,"value"));
    argsType指定了參數的類型。
    ?
    六、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的源碼中取得,只做了簡單的修改,沒有加多余的注釋。如果要正式使用,
    需要再做精加工。
    原貼地址:http://www.54bk.com/user1/7053/archives/2006/200610269924.html
    posted on 2006-11-09 11:21 OMG 閱讀(2028) 評論(0)  編輯  收藏 所屬分類: Utils公用類/commons

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    <2006年11月>
    2930311234
    567891011
    12131415161718
    19202122232425
    262728293012
    3456789

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    IT風云人物

    文檔

    朋友

    相冊

    經典網站

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 成人a毛片免费视频观看| 亚洲精品9999久久久久无码| 一级大黄美女免费播放| 全免费一级午夜毛片| 国产日本亚洲一区二区三区| 最近最新MV在线观看免费高清 | 日本亚洲视频在线| 免费观看在线禁片| 麻豆亚洲av熟女国产一区二| 91麻豆国产免费观看| 亚洲成av人片不卡无码| 蜜臀AV免费一区二区三区| 亚洲AV无码成人专区| 免费高清资源黄网站在线观看| 亚洲欧美熟妇综合久久久久| 国产视频精品免费| 一本岛v免费不卡一二三区| 亚洲人成人网站在线观看| a在线观看免费网址大全| 亚洲AV日韩精品久久久久久| 免费无码VA一区二区三区| 亚洲影院在线观看| 好先生在线观看免费播放| 亚洲高清一区二区三区电影| 狠狠色婷婷狠狠狠亚洲综合| 久久精品乱子伦免费| 亚洲国产视频久久| 四虎永久精品免费观看| 中文字幕永久免费视频| 亚洲激情黄色小说| 日本二区免费一片黄2019| 三年在线观看免费观看完整版中文| 亚洲国产高清在线| 四虎影院免费视频| 精选影视免费在线 | 91午夜精品亚洲一区二区三区| 天天摸天天操免费播放小视频 | 亚洲中文无码线在线观看| 永久免费AV无码网站在线观看| 热久久这里是精品6免费观看| 亚洲av片不卡无码久久|