欢迎光临
我们一直在努力

Jakarta-Common-BeanUtils研究心得(2)-JSP教程,资料/其它

建站超值云服务器,限时71元/月

允许随意转载,但请注明出处及作者。

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

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 applications
* 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的源码中取得,只做了简单的修改,没有加多余的注释。如果要正式使用,
需要再做精加工。

========================================
关于这个包,只准备测试到这里了,不过已经有了大概的印象了,至少,知道这个包可以做些什么。
其实这个笔记也只是起到这个作用。@_@

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » Jakarta-Common-BeanUtils研究心得(2)-JSP教程,资料/其它
分享到: 更多 (0)

相关推荐

  • 暂无文章