分页参考1
既然讲的是 Struts ,那自然离不了 MVC ,分页显示也是如此。
1 、 建立数据库和对应的表,本例的表是 TCertificate 。
2 、 建立适当的模型组件,对应你要查询数据库中的表。这部分由 DAO 数据访问层来实现,如果有的朋友对 DAO 不熟悉可以查询一下相关资料。本例由 CertificateDAO.java 来实现。
3 、建立分页所需要的模型组件,由 javaBean 来充当,并与 CertificateDAO 实现分离。网上介绍的很多方法,都存在着数据与分页组件藕合的现象,这也是本方法与其它分页方法的主要不同之处。
4 、建立控制器组件,这部分由 Struts 中的 Action 来实现。主要负责将实例化 CertificateDAO ,只取要显示的数据记录,存入 ArrayList 对象然后返回,并放到 request 中。而分页部分则根据分页条件,单独进行构造,避免了与 DAO 混在一起的情况发生。网上其它介绍的一些分页方法中,基本上都是一次性读出所 有查询的数据,然后再由分页相关组件进行构造。这样,如果数据量大的话,很容易形成瓶颈。在本例中由于不是一次性地读出查询的所有数据,而只是读出一个页 面要显示的数据记录,这就节省了很多不必要的数据传输,提高了效率。本例中为 CertificateAction.java 。
5 、建立视图组件,这部分由 jsp 来充当,为了不出现 java 代码,我们使用 Struts 提供的标签库,主要负责从 request 中取出刚刚放入的对象,通过反复调用 CertificateAction 以及 action 参数,而实现分页显示。本例中为 listcertificate.jsp 。
6 、 建立并配置 struts-config.xml 。
三、实例代码
确定好上面的开发思路后,代码的实现就有单可循了。
1 、建数据库和相应的表。
2 、数据逻辑层的相关代码。
1 )、通用的 DAO 类: CommonDAO.java
这是一个很多 DAO 都要继承到的通用 DAO 类,是我根据实践总结出来的,为了减少篇幅,这里只显示和本例相关的代码。
java 代码 :
代码:
--------------------------------------------------------------------------------
package com.xindeco.business ;
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.sql.*;
import java.lang.IllegalAccessException;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtils;
public class DAO
{
protected DataSource ds;
/**
* 说明 : 取得当前查询的总记录数
*/
public int getRows ()
{
return this.count;
}
public void rsHandler (ResultSet rs, int offset, int limit)
{
try
{
count = 0;
rs.absolute ( -1) ;
count = rs.getRow () ;
if (offset <= 0)
{
rs.beforeFirst () ;
}
else
{
rs.absolute (offset) ;
}
}
catch (Exception e)
{
e.printStackTrace () ;
}
}
public DAO(DataSource ds) {
this.ds = ds;
}
public void setDataSource(DataSource ds) {
this.ds = ds;
}
protected void close(ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
}
rs = null;
}
}
protected void close(PreparedStatement pstmt) {
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
}
pstmt = null;
}
}
protected void close(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
protected void rollback(Connection conn) {
if (conn != null) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
这个类主要是通过子类传进来的先进结果集,取得查询的记录总数,并对数据库连接进行简单的管理。
2 )、对数据库进行访问: CertificateDAO.java
java 代码 :
代码:
--------------------------------------------------------------------------------
package com.xindeco.business;
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.sql.*;
import com.xindeco.common.dbconn.DbConn;
public class CertificateDAO extends DAO
{
public NationDAO(DataSource ds) {
super(ds);
}
public List findCertificateList(int offset,int limit) throws SQLException
{
int countRows = 0 ;
ArrayList list = null ;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
conn = ds.getConnection();
String sql =
"SELECT certificateID, certificateCode,certificateName,photoURL,"
+ "des.c.r.i.p.tion,graduateID FROM TCertificate " ;
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
/* 对游标进行处理, rsHandler 方法在父类 DAO 中 */
this.rsHandler(rs,offset,limit);
if (rs != null && rs.next ())
{
list = new ArrayList () ;
do
{
countRows++ ;
list.add (rs2VO (rs)) ;
}
while ( (countRows++ < limit) && rs.next ()) ;
}
close(rs);
close(pstmt);
} catch (SQLException e) {
close(rs);
close(pstmt);
rollback(conn);
e.printStackTrace();
}
finally {
close(conn);
}
return list ;
}
private CertificateVO rs2VO (ResultSet rs)
{
try
{
CertificateVO certificateVO = new CertificateVO () ;
certificateVO.setCertificateID (rs.getInt ("certificateID")) ;
certificateVO.setCertificateCode (rs.getString ("certificateCode")) ;
certificateVO.setCertificateName (rs.getString ("certificateName")) ;
certificateVO.setPhotoURL (rs.getString ("photoURL")) ;
certificateVO.setDes.c.r.i.p.tion (rs.getString ("des.c.r.i.p.tion")) ;
certificateVO.setGraduateID (rs.getInt ("graduateID")) ;
return certificateVO ;
}
catch (Exception ex)
{
ex.printStackTrace () ;
return null ;
}
}
}
findCertificateList(int offset,int limit) 是查得所有要显示的数据,并放入 ArrayList 中。看过网上有些例子,把数据记录放入 ArrayList 的动作过程直接在 while 循环 体里完成,如果字段多的话,会造成方法过于宠大,又不美观。 这里,数据记录放入 ArrayList 的动作过程由 rs2VO 方法完成,就比较整洁了。另外, if (rs != null && rs.next ()) 配合 while ( (countRows++ < limit) && rs.next ()) 是为了程序的健壮性考虑的,稍分析一下不难得出结论。