??xml version="1.0" encoding="utf-8" standalone="yes"?>精品国产三区在线,欧美一二区在线观看,一区二区网站http://www.aygfsteel.com/wangyong/archive/2007/08/02/133919.htmlCoolYongZiCoolYongZiThu, 02 Aug 2007 01:49:00 GMThttp://www.aygfsteel.com/wangyong/archive/2007/08/02/133919.htmlhttp://www.aygfsteel.com/wangyong/comments/133919.htmlhttp://www.aygfsteel.com/wangyong/archive/2007/08/02/133919.html#Feedback0http://www.aygfsteel.com/wangyong/comments/commentRss/133919.htmlhttp://www.aygfsteel.com/wangyong/services/trackbacks/133919.html阅读全文

CoolYongZi 2007-08-02 09:49 发表评论
]]>
ZJDBC的数据库q接池高效管理策?/title><link>http://www.aygfsteel.com/wangyong/archive/2007/08/01/133822.html</link><dc:creator>CoolYongZi</dc:creator><author>CoolYongZi</author><pubDate>Wed, 01 Aug 2007 08:15:00 GMT</pubDate><guid>http://www.aygfsteel.com/wangyong/archive/2007/08/01/133822.html</guid><wfw:comment>http://www.aygfsteel.com/wangyong/comments/133822.html</wfw:comment><comments>http://www.aygfsteel.com/wangyong/archive/2007/08/01/133822.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/wangyong/comments/commentRss/133822.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/wangyong/services/trackbacks/133822.html</trackback:ping><description><![CDATA[<p>在基于JDBC的数据库应用开发中Q数据库q接的管理是一个难点,因ؓ(f)它是军_该应用性能的一个重要因素。本文在Ҏ(gu)据库q接q行透彻分析的基上,提出q实C(jin)一个高效的q接理{略Q得开发高性能的数据库应用变得相对Ҏ(gu)。特别是Q对于连接管理中的两个难点:(x)事务和多U程问题q行?jin)深入的剖析Qƈl出?jin)一个基于设计模式的解决Ҏ(gu)?br>介绍</p> <p>在用Java语言q行和数据库有关的的应用开发中Q一般都使用JDBC来进行和数据库的交互Q其中有一个关键的概念是ConnectionQ连接)(j)Q它在Java中是一个类Q代表了(jin)一个通道。通过它,使用数据的应用就可以从数据库讉K数据?jin)?/p> <p>对于一个简单的数据库应用,׃对于数据库的讉K不是很频J。这时可以简单地在需要访问数据库Ӟ新创徏一个连接,用完后就关闭它,q样做也不会(x)带来什么明昄性能上的开销。但是对于一个复杂的数据库应用,情况完全不同了(jin)。频J的建立、关闭连接,?x)极大的减低pȝ的性能Q因为对于连接的使用成了(jin)pȝ性能的瓶颈?/p> <p>本文l出的方法可以有效的解决q个问题。在本方法中提出?jin)一个合理、有效的q接理{略Q避免了(jin)对于q接的随意、无规则的用。该{略的核?j)思想是:(x)q接复用。通过建立一个数据库q接池以?qing)一套连接用管理策略,使得一个数据库q接可以得到高效、安全的复用Q避免了(jin)数据库连接频J徏立、关闭的开销。另外,׃对JDBC中的原始q接q行?jin)封装,从而方便了(jin)数据库应用对于连接的使用Q特别是对于事务处理Q,提高?jin)开发效率,也正是因个封装层的存在,隔离?jin)应用的本n的处理逻辑和具体数据库讉K逻辑Q应用本n的复用成为可能?/p> <p>问题产生\r</p> <p>我参与的目是开发一个网系l,不可避免的要和数据库打交道。刚开始时Q由于对于数据库的访问不是很频繁Q对于数据库q接的用就是简单的需要时徏立,用完关闭的{略Q这很符合XPQeXtreme ProgrammingQ的口号Q?Do the Simplest Thing that Could Possibly Work"。确实,开始时工作的很好。随着目的进展,对于数据库的讉K开始变的频J,问题暴露出来了(jin)Q原先的通过单地获取和关闭数据库q接的方法将很大的媄(jing)响系l的性能Q这U媄(jing)响是׃数据库资源管理器q程频繁的创建和摧毁那些q接对象而引L(fng)?/p> <p>此时Q就有必要对数据库访问方法进行重构(refactoringQ,因ؓ(f)我们实需要进行改q,来提高系l的性能?/p> <p>解决Ҏ(gu)</p> <p>可以看出Q问题的Ҏ(gu)是׃对于q接资源的低效管理造成的。对于共享资源,有一个很著名的设计模式:(x)资源池。该模式正是Z(jin)解决资源频繁分配、释放所造成的问题的。把该模式应用到数据库连接管理领域,是建立一个数据库q接池,提供一套高效的q接分配、用策略,最l目标是实现q接的高效、安全的复用?/p> <p>3.1、徏立连接池</p> <p>W一步,是要徏立一个静(rn)态的q接池,所谓静(rn)态是指,池中的连接是在系l初始化时就分配好的Qƈ且不能够随意关闭的。Java中给我们提供很多容器cd以方便的用来构徏q接池,如:(x)Vector、Stack{。在pȝ初始化时Q根据配|创接ƈ攄在连接池中,以后所使用的连接都是从该连接池中获取的Q这样就可以避免q接随意建立、关闭造成的开销Q当?dng)我们没有办法避免Java的Garbage Collection带来的开销Q?/p> <p>3.2、分配、释攄?/p> <p>有了(jin)q个q接池,下面我们可以提供一套自定义的分配、释攄略?/p> <p>当客戯求数据库q接Ӟ首先看连接池中是否有I闲q接Q这里的I闲是指Q目前没有分配出ȝq接。如果存在空闲连接则把连接分配给客户Qƈ作相应处理,具体处理{略Q在关键议题中会(x)详述Q主要的处理{略是标记该连接ؓ(f)已分配。若q接池中没有I闲q接Q就在已l分配出ȝq接中,L一个合适的q接l客P选择{略?x)在关键议题中详qͼ(j)Q此时该q接在多个客户间复用?/p> <p>当客户释放数据库q接Ӟ可以Ҏ(gu)该连接是否被复用Q进行不同的处理。如果连接没有用者,放入到q接池中Q而不是被关闭?/p> <p>可以看出正是q套{略保证?jin)数据库q接的有效复用?/p> <p>3.3、配|策?/p> <p>数据库连接池中到底要攄多少个连接,q接耗尽后该如何处理呢?q时一个配|策略。一般的配置{略是,开始时Q根据具体的应用需求,l出一个初始的q接池中q接的数目以?qing)一个连接池可以扩张到的最大连接数目。本Ҏ(gu)是按照q种{略实现的?/p> <p>关键议题\r</p> <p>本节对上述解决Ҏ(gu)中的关键l节q行详述Q正是这些关键的{略保证?jin)数据库q接复用的高效和安全?/p> <p>4.1、引用记?/p> <p>3.2节中的分配、释攄略对于有效复用连接非帔R要,我们采用的方法也是采用了(jin)一个很有名的设计模式:(x)Reference CountingQ引用记敎ͼ(j)。该模式在复用资源方面用的非常广泛,我们把该Ҏ(gu)q用到对于连接的分配释放上。每一个数据库q接Q保留一个引用记敎ͼ用来记录该连接的使用者的个数。具体的实现上,我们采用?jin)两极连接池Q空闲池和用池。空闲池中存攄前还没有分配出去被用的q接Q一旦一个连接被分配出去Q那么就?x)放入到使用池中Qƈ且增加引用记数?/p> <p>q样做有一个很大的好处Q得我们可以高效的使用q接Q因Z旦空闲池中的q接被全部分配出去,我们可以根据相应的{略从用池中挑选出一个已l正在用的q接用来复用Q而不是随意拿Z个连接去复用。策略可以根据需要去选择Q我们采用的{略比较单:(x)复用引用记数最的q接。Java的面向对象特性,使得我们可以灉|的选择不同的策略(提供一个不同策略共用的抽象接口Q各个具体的{略都实现这个接口,q样对于{略的处理逻辑和{略的实现逻辑分离Q?/p> <p>4.2、事务处理\r</p> <p>前面谈到的都是关于用数据库q接q行普通的数据库访问。对于事务处理,情况变得比较复杂。因Z务本w要求原子性的保证Q此时就要求对于数据库的操作W合"All-All-Nothing"原则Q即要么全部完成Q要么什么都不做。如果简单的采用上述的连接复用的{略Q就?x)发生问题,因?f)没有办法控制属于同一个事务的多个数据库操作方法的动作Q可能这些数据库操作是在多个q接上进行的Qƈ且这些连接可能被其他非事务方法复用?/p> <p>Connection本nh提供?jin)对于事务的支持Q可以通过讄Connection的AutoCommit属性ؓ(f)falseQ显式的调用commit或者rollbackҎ(gu)来实现。但是要安全、高效的q行Connectionq行复用Q就必须提供相应的事务支持机制。我们采用的Ҏ(gu)是:(x)采用昑ּ的事务支撑方法,每一个事务独占一个连接。这U方法可以大大降低对于事务处理的复杂性(如果事务不独占一条连接,那么要保证事务的原子性ƈ且又不妨复用该q接的其他和该事务无关的操作Q基本上不可能,除非ConnectioncL你开发的Q,q且又不?x)妨连接的复用Q因为隶属于该事务的所有数据库操作都是通过q一个连接完成的Qƈ且事务方法又复用?jin)其他一些数据库Ҏ(gu)?/p> <p>在我们的q接理服务提供?jin)显式的事务开始、结束(commit或者rollbackQ声明,以及(qing)一个事务注册表Q用于登C务发赯(g)和事务使用的连接的对应关系Q通过该表Q用事务的部分和我们的q接理部分隔dQ因表是在运行时Ҏ(gu)实际的调用情况,动态生成的。事务用的q接在该事务q行中不能被复用?/p> <p>当用者需要用事务方法时Q首先调用连接管理服务提供的beginTransҎ(gu)Q该Ҏ(gu)主要处理程如下(伪码描述)Q?/p> <p>           public void beginTrans( ) {<br>                    …<br>                conn = getIdleConnectionFromPoll( );<br>                userId = getUserId( );<br>                registerTrans(userId, conn);<br>                    …<br>} </p> <p><br> </p> <p> </p> <p>在我们的实现中,用户标识是通过使用者所在的U程来标识的。后面的所有对于数据库的访问都是通过查找该注册表Q用已l分配的q接来完成的。当事务l束Ӟ从注册表中删除相应表V?/p> <p>对于嵌套的事务如何处理呢Q我们采用的Ҏ(gu)仍ؓ(f)引用记数Q不q这里的引用记数是指?嵌套层次"Q具体的l节Q不再赘q?/p> <p>4.3、封?/p> <p>从上面的可以看出Q普通的数据库方法和事务Ҏ(gu)对于q接的用(分配、释放)(j)是不同的Qؓ(f)?jin)便于用,对外提供一致的操作接口Q我们对q接q行?jin)封装?x)x通连接和事务q接。在此,我们利用?jin)Java中的强大的面向对象特性:(x)多态。普通连接和事务q接均实C(jin)一个DbConnection接口Q对于接口中定义的方法,分别Ҏ(gu)自己的特点作?jin)不同的实现Q这样在对于q接的处理上非常的一致了(jin)?/p> <p>4.4、ƈ发问题\r</p> <p>Z(jin)是我们的q接理服务有更大的通用性,必要考虑到多U程环境Q即q发问题。在一个多U程的环境下Q我们必要保证q接理自n数据的一致性和q接内部数据是一致性,q好Java提供对这斚w的很好的支持Qsynchronized关键字)(j)Q这h们就很容易ɘq接理成ؓ(f)U程安全的?/p> <p>5、结?/p> <p>本文l出?jin)一个基本的q接理框架Q在其中使用?jin)一些广泛用的设计模式Q资源池Q引用记数等Q,使得高效、安全的复用数据库连接成为可能。当?dng)q有一些问题没有考虑刎ͼ比如Q没有实现对不同U类的数据库的联合管理;没有提供定时(g)机Ӟ查询q接的状态等。另外在q接理的用包装上比v一些商用的pȝq显_糙Q但是底层的基理是一致的Q所以通过本文怿对于q些商用的品中的相兛_能会(x)有更好的理解?/p> <p>参考文?br>《Thinking in Java》Bruce Eckel</p> <p>《Real-Time Design Patterns?Bruce Powel Dougladd<br></p> <img src ="http://www.aygfsteel.com/wangyong/aggbug/133822.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/wangyong/" target="_blank">CoolYongZi</a> 2007-08-01 16:15 <a href="http://www.aygfsteel.com/wangyong/archive/2007/08/01/133822.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts分页http://www.aygfsteel.com/wangyong/archive/2007/08/01/133821.htmlCoolYongZiCoolYongZiWed, 01 Aug 2007 08:11:00 GMThttp://www.aygfsteel.com/wangyong/archive/2007/08/01/133821.htmlhttp://www.aygfsteel.com/wangyong/comments/133821.htmlhttp://www.aygfsteel.com/wangyong/archive/2007/08/01/133821.html#Feedback0http://www.aygfsteel.com/wangyong/comments/commentRss/133821.htmlhttp://www.aygfsteel.com/wangyong/services/trackbacks/133821.html拜读?jin)bibiye的《一个高效简z的Struts分页Ҏ(gu)(原创)》后Q根据bibiye的方法,自己修改?jin)一下,也弄?jin)一个struts下的分页Q大家见W了(jin)Q?/p>

我的Ҏ(gu)是,Ҏ(gu)用户点击D条上的页?offset)Q到DB中读取该늚数据(不是一ơ全部读?Q点到哪读哪页的数据,JBX + tomcat + oracle下测试通过Q数据库用的表是oracle的emp表?/p>

********分页cPager.javaQ负责生成分导航条********

package page;

/**
 * 分页代码
 * <p>Title: 分页</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2005</p>
 * <p>Company: BCS</p>
 * @author Alex
 * @version 1.0
 */
public class Pager {
  private int offset;
  private int size;
  private int length;
  private String url;
  private String pageHeader;
  public Pager(int offset, int size, int length, String url, String pageHeader) {
    this.offset = offset;
    this.size = size;
    this.length = length;
    this.url = url;
    this.pageHeader = pageHeader;
  }

  /**
   * q回分页D?br>   * @param offset int 起始记录的位|?br>   * @param size int 总记录数
   * @param length int 步长
   * @param url String .do的url
   * @param pageHeader String D条的前缀文字提示
   * @return String
   */
  public String getPageNavigation() {
    String pageNavigation = ""; //最l返回的分页D?br>    //记录数超q一?需要分?br>    if (size > length) {
      String pref; //前缀
      if (url.indexOf("?") > -1) {
        //如果url中已l包含了(jin)其他的参?把offset参数接在后面
        pref = "&";
      }
      else {
        //如果url中没有别的参?br>        pref = "?";
      }
      //如果D条包含header
      if (pageHeader != null && pageHeader.length() > 0) {
        pageNavigation = pageHeader + " : ";
      }
      //如果不是W一?D条将包含“<<”(W一??#8220;<”(前一?
      if (offset > 0) {
        pageNavigation += "<a href='" + url + pref + "offset=0'>[<<]</a>\n" +
            "<a href='" + url + pref + "offset=" + (offset - length) +
            "'>[<]</a>\n";
      }
      //D条中,排头的那一늚offset?br>      int startOffset;
      //位于D条中间的那一늚offset?半径)
      int radius = constants.MAX_PAGE_INDEX / 2 * length;
      //如果当前的offset值小于半?br>      if (offset < radius || this.pageCount() <= constants.MAX_PAGE_INDEX) {
        //那么W一|?br>        startOffset = 0;
      }
      else if (offset < size - radius) {
        startOffset = offset - radius;
      }
      else {
        startOffset = (size / length - constants.MAX_PAGE_INDEX) * length;
      }
      for (int i = startOffset;
           i < size && i < startOffset + constants.MAX_PAGE_INDEX * length;
           i += length) {
        if (i == offset) {
          //当前号,加粗昄
          pageNavigation += "<b>" + (i / length + 1) + "</b>\n";
        }
        else {
          //其他号,包含链?br>          pageNavigation += "<a href='" + url + pref + "offset=" + i + "'>" +
              (i / length + 1) + "</a>\n";
        }
      }
      //如果不是最后一?D条将包含“>”(下一??#8220;>>”(最后一?
      if (offset < size - length) {
        pageNavigation += "<a href='" + url + pref + "offset=" +
            (offset + length) + "'>[>]</a>\n" +
            "<a href='" + url + pref + "offset=" + lastPageOffset() +
            "'>[>>]</a>\n";
      }
//      System.out.println("radius : " + radius);
//      System.out.println("start offset : " + startOffset);
      return pageNavigation;
    }
    //记录不超q一?不需要分?br>    else {
      return "";
    }
  }

  /**
   * q回分页后的总页?br>   * @param size int 总记录数
   * @param length int 每页的记录数
   * @return int
   */
  public int pageCount() {
    int pagecount = 0;
    if (size % length == 0) {
      pagecount = size / length;
    }
    else {
      pagecount = size / length + 1;
    }
    return pagecount;
  }

  /**
   * q回最后一늚记录?br>   * @param size int 总记录数
   * @param length int 每页的记录数
   * @return int
   */
  public int lastPageSize() {
    int lastpagesize = 0;
    if (size % length == 0) {
      lastpagesize = length;
    }
    else {
      lastpagesize = size % length;
    }
    return lastpagesize;
  }

  /**
   * q回最后一늚起始记录位置
   * @param size int 总记录数
   * @param length int 每页的记录数
   * @return int
   */
  public int lastPageOffset() {
    return size - lastPageSize();
  }

  public int getOffset() {
    return offset;
  }

  public void setOffset(int offset) {
    this.offset = offset;
  }

  public int getSize() {
    return size;
  }

  public void setSize(int size) {
    this.size = size;
  }

  public int getLength() {
    return length;
  }

  public void setLength(int length) {
    this.length = length;
  }

  public String getUrl() {
    return url;
  }

  public void setUrl(String url) {
    this.url = url;
  }

  public String getPageHeader() {
    return pageHeader;
  }

  public void setPageHeader(String pageHeader) {
    this.pageHeader = pageHeader;
  }
}

********数据处理cempDAO.javaQ负责访问DBQ获取当前页面需要显C的记录********

package page;

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

public class empDAO {
  public empDAO() {
  }

  /**
   * 从offset位置起始,q回length条记?br>   * @param offset int 起始的记录位|?br>   * @param length int 步长
   * @param conn Connection 数据库连?br>   * @return ArrayList
   */
  public ArrayList findAllEmp(int offset, int length, Connection conn) throws
      SQLException {
    PreparedStatement ps = null;
    ResultSet rs = null;
    ArrayList emps = new ArrayList();
    empVO empvo = null;
    String strSql = "select empno, ename from emp where rowid not in (select rowid from emp where rownum <= ?) and rownum <= ?";
    try {
      ps = conn.prepareStatement(strSql);
      ps.setInt(1, offset); //起始记录的位|?br>      ps.setInt(2, length); //步长
      rs = ps.executeQuery();
      while (rs != null && rs.next()) {
        empvo = new empVO();
        empvo.setEmpno(rs.getInt("empno"));
        empvo.setEname(rs.getString("ename"));
        emps.add(empvo);
      }
    }
    catch (SQLException ex) {
      ex.printStackTrace();
      throw ex;
    }
    return emps;
  }

  /**
   * q回ȝ记录?br>   * @param conn Connection
   * @throws SQLException
   * @return int
   */
  public int getRsTotalCount(Connection conn) throws SQLException {
    PreparedStatement ps = null;
    ResultSet rs = null;
    int rsCount = 0;
    String strSql = "select count(empno) as empCount from emp";
    try {
      ps = conn.prepareStatement(strSql);
      rs = ps.executeQuery();
      if (rs != null && rs.next()) {
        rsCount = rs.getInt("empCount");
      }
    }
    catch (SQLException ex) {
      ex.printStackTrace();
      throw ex;
    }
    return rsCount;
  }
}

********业务cempBO.javaQ调用empDAOc?*******

package page;

import java.util.*;

/**
 * BOc?br> * <p>Title: 分页</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2005</p>
 * <p>Company: BCS</p>
 * @author Alex
 * @version 1.0
 */
public class empBO {
  private DBPool db = DBPool.newInstance();
  private empDAO empdao = new empDAO();

  public empBO() {
  }

  /**
   * 从offset位置起始,q回length条记?br>   * @param offset int 起始
   * @param length int 步长
   * @throws Exception
   * @return ArrayList
   */
  public ArrayList findAllEmp(int offset, int length) throws Exception {
    ArrayList emps = new ArrayList();
    try {
      emps = empdao.findAllEmp(offset, length, db.getConnection());
    }
    catch (Exception ex) {
      throw ex;
    }
    finally {
      db.release();
    }
    return emps;
  }

  /**
   * q回ȝ记录?br>   * @throws Exception
   * @return int
   */
  public int getRsTotalCount() throws Exception {
    int rsCount = 0;
    try {
      rsCount = empdao.getRsTotalCount(db.getConnection());
    }
    catch (Exception ex) {
      throw ex;
    }
    finally {
      db.release();
    }
    return rsCount;
  }
}


********ActionFormcempForm.java********

package page;

import javax.servlet.http.*;

import org.apache.struts.action.*;

public class empForm
    extends ActionForm {
  private int offset; //起始记录的位|?/每页昄的记录数
  public ActionErrors validate(ActionMapping actionMapping,
                               HttpServletRequest httpServletRequest) {
    /**@todo: finish this method, this is just the skeleton.*/
    return null;
  }

  public void reset(ActionMapping actionMapping,
                    HttpServletRequest httpServletRequest) {
    this.offset = 0; //记录默认从第一条开始显C?br>  }

  public int getOffset() {
    return offset;
  }

  public void setOffset(int offset) {
    this.offset = offset;
  }

}


********ActioncempAction.javaQ控制器Q调用BOc,Pagerc?*******

package page;

import java.util.*;
import javax.servlet.http.*;

import org.apache.struts.action.*;

/**
 * 分页试的Action
 * <p>Title: 分页</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2005</p>
 * <p>Company: BCS</p>
 * @author Alex
 * @version 1.0
 */
public class empAction
    extends Action {

  public ActionForward execute(ActionMapping actionMapping,
                               ActionForm actionForm,
                               HttpServletRequest httpServletRequest,
                               HttpServletResponse httpServletResponse) {
    empForm empform = (empForm) actionForm;
    return performList(actionMapping, actionForm, httpServletRequest,
                       httpServletResponse);
  }

  private ActionForward performList(ActionMapping actionMapping,
                                    ActionForm actionForm,
                                    HttpServletRequest request,
                                    HttpServletResponse response) {
    try {
      empBO empbo = new empBO();
      //获取外部传进来的起始记录?br>      int offset = ( (empForm) actionForm).getOffset();
      //获取每页的记录数
      int pagesize = constants.PAGE_SIZE;
      //获取记录集合,从offset开?取length条记?br>      ArrayList emps = empbo.findAllEmp(offset, pagesize);
      //计算所有记录的条数(总记录数)
      int size = empbo.getRsTotalCount();
      //外部url地址,得到形如: http://localhost:8088/bugMIS/showlist.do 的String
      String url = request.getContextPath() + actionMapping.getPath() + ".do";
      //实例化分늱
      Pager p = new Pager(offset, size, pagesize, url, "Page Navigation");
      //获取分页D?br>      //String pageNavigation = p.getPageNavigation();
      //url字符串和记录集合,存入request?br>      request.setAttribute("pager", p);
      request.setAttribute("emps", emps);
    }
    catch (Exception e) {
      e.printStackTrace();
      return actionMapping.findForward("failure");
    }
    return actionMapping.findForward("success");
  }
}


********数据库连接池cDBPool.javaQ可以用tomcat的连接池Q也可以不用Q这里关闭了(jin)********

package page;

import java.sql.*;
import javax.naming.*;
import javax.sql.*;

import org.apache.commons.logging.*;

/**
 * pȝq接池类
 * <p>Title: Gantoo@91.com</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2005</p>
 * <p>Company: BCS</p>
 * @author Alex
 * @version 1.0
 */
public class DBPool {
  Log log = LogFactory.getLog("DBPool"); //日志?br>  private DBPool() {
  }

  private Connection conn = null;

  /* true:使用q接?br>     false:不用连接池,采用JDBC直接q接 */
  private final static boolean USE_DB_POOL = false;
  private final static String jndi_DataSource = "jdbc/BugMIS_ora";
  private final static String jdbcdriver =
      "oracle.jdbc.driver.OracleDriver";
  private final static String url =
      "jdbc:oracle:thin:@localhost:1521:myo9";
  private final static String user = "scott";
  private final static String pass = "tiger";

  public static DBPool newInstance() {
    return new DBPool();
  }

  /**
   * 切换是否使用q接?br>   * */
  public Connection getConnection() {
    if (USE_DB_POOL) {
      conn = getConnectionByDBPool();
    }
    else {
      conn = getConnectionDirect();
    }
    return conn;
  }

  /**
   * 直接采用JDBCq接数据?br>   * */
  private Connection getConnectionDirect() {
    try {
      Class.forName(jdbcdriver).newInstance();
      conn = DriverManager.getConnection(url, user, pass);
    }
    catch (SQLException ex) {
      log.error("Error Connection! " + ex.getMessage());
    }
    catch (ClassNotFoundException ex) {
      log.error("Driver Not Found! " + ex.getMessage());
    }
    catch (IllegalAccessException ex) {
      log.error(ex.getMessage());
    }
    catch (InstantiationException ex) {
      log.error(ex.getMessage());
    }
    return conn;
  }

  /**
   * 采用q接?br>   * */
  private Connection getConnectionByDBPool() {
    try {
      Context initCtx = new InitialContext();
      Context ctx = (Context) initCtx.lookup("java:/comp/env");
      DataSource ds = (DataSource) ctx.lookup(jndi_DataSource);
      conn = ds.getConnection();
    }
    catch (NamingException ex) {
      log.error("Data Source Not Found! " + ex.getMessage());
      //System.out.println("未找到数据源" + ex.getMessage());
    }
    catch (SQLException ex1) {
      log.error("Error Connection! " + ex1.getMessage());
      //System.out.println("错误的数据连? + ex1.getMessage());
    }
    return conn;
  }

  /**
   * 释放q接
   * */
  public void release() {
    try {
      if (!conn.isClosed()) {
        conn.close();
      }
    }
    catch (SQLException ex) {
      log.error("Connection Closing Error! " + ex.getMessage());
      //System.out.println("q接关闭p|" + ex.getMessage());
    }
  }
}


********包含帔R的类constants.javaQ常?*******

package page;

/**
 * 定义工程中公用的帔R
 * <p>Title: 分页</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2005</p>
 * <p>Company: BCS</p>
 * @author Alex
 * @version 1.0
 */
public final class constants {
  public static final int MAX_PAGE_INDEX = 5; //脚昄多少?br>  public static final int PAGE_SIZE = 2; //每页的记录数
}


********试jsp面index.jspQؓ(f)?jin)方便测试,嵌入了(jin)java代码Q能昄p********

<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ page contentType="text/html; charset=GBK" import="java.util.*,page.*"%>
<html:html>
<head>
<title></title>
<style type="text/css">
.pt9 {  font: 10pt "宋体"}
body { font: 10pt "宋体" ; margin: 15px}
td {  font-size: 10pt}
a:hover {  font-size: 10pt; color: red; text-decoration: underline}
a:link {  font-size: 10pt; color: blue; text-decoration: underline}
a:active {  font-size: 10pt; color: blue; text-decoration: underline}
a:visited { font-size: 10pt; color: blue; text-decoration: underline }
</style>
</head>
<body bgcolor="#ffffff">

<p><a href="http://localhost:8088/page/showEmp.do?offset=0">Show Me All Of The Emps</a></p>

<logic:present name="emps">
  <%
  ArrayList emps = (ArrayList)request.getAttribute("emps");
  Iterator it = emps.iterator();
  empVO empvo;
  while(it!=null && it.hasNext()){
    empvo = (empVO)it.next();
    out.print(empvo.getEmpno() + "  ");
    out.print(empvo.getEname() + "<br>");
  }
    out.print("当前| " + emps.size() + " 条记?lt;br>");
    out.print("<p>");
  %>
</logic:present>

<logic:present name="pager">
  <%
  Pager pager = (Pager)request.getAttribute("pager");
  out.print(pager.getPageNavigation() + "<p>");
  out.print("共有记录 " + pager.getSize() + " ?lt;br>");
  out.print("每页?" + pager.getLength() + " 条记?lt;br>");
  out.print("共分 " + pager.pageCount() + " ?lt;br>");
  %>
</logic:present>
</body>
</html:html>

********配置文gstruts-config.xml********

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "<struts-config>
  <form-beans>
    <form-bean name="empForm" type="page.empForm" />
  </form-beans>
  <action-mappings>
    <action input="/index.jsp" name="empForm" path="/showEmp" scope="request" type="page.empAction" validate="false">
      <forward name="faiure" path="/index.jsp" />
      <forward name="success" path="/index.jsp" />
    </action>
  </action-mappings>
</struts-config>

 

 


在网上看?jin)几个Structs分页Q感觉不是很完善Q于是根据自ql验Q写?jin)一个相寚w效简z的分页Ҏ(gu)。由于本人水qx限,如果大家有什么更好的xQ欢q不吝赐教?br>  
  一?开发环?br>  
  我的开发环境是QJBuilder x + Weblogic 8.1 + Oracle 9i + Windows 2003 Q如果朋友们的开发环境不一样亦无妨?br>  
  二、开发思\
  
  既然讲的是StrutsQ那自然M?jin)MVCQ分|CZ是如此?br>  
  1?建立数据库和对应的表Q本例的表是TCertificate?br>  
  2?建立适当的模型组Ӟ对应你要查询数据库中的表。这部分由DAO数据讉K层来实现Q如果有的朋友对DAO不熟(zhn)可以查询一下相兌料。本例由CertificateDAO.java来实现?br>  
  3 、徏立分|需要的模型lgQ由javaBean来充当,q与CertificateDAO实现分离。网上介l的很多Ҏ(gu)Q都存在着数据与分늻件藕合的现象Q这也是本方法与其它分页Ҏ(gu)的主要不同之处?br>  
  4、徏立控制器lgQ这部分由Struts 中的Action来实现。主要负责将实例化CertificateDAOQ只取要昄的数据记录,存入ArrayList对象然后q回Qƈ攑ֈrequest中。而分部分则Ҏ(gu)分页条gQ单独进行构造,避免?jin)与DAO混在一L(fng)情况发生。网上其它介l的一些分|法中Q基本上都是一ơ性读出所有查询的数据Q然后再由分늛关组件进行构造。这P如果数据量大的话Q很Ҏ(gu)形成瓉。在本例中由于不是一ơ性地d查询的所有数据,而只是读Z个页面要昄的数据记录,q就节省?jin)很多不必要的数据传输,提高了(jin)效率。本例中为CertificateAction.java?br>  
  5、徏立视囄Ӟq部分由jsp来充当,Z(jin)不出现java 代码Q我们用Struts提供的标{ֺQ主要负责从request中取出刚刚放入的对象Q通过反复调用CertificateAction以及(qing)action参数Q而实现分|C。本例中为listcertificate.jsp?br>  
  6?建立q|struts-config.xml?br>  
  三、实例代?br>  
  定好上面的开发思\后,代码的实现就有单可@?jin)?br>  
  1、徏数据库和相应的表?br>  
  2、数据逻辑层的相关代码?br>  
  1Q、通用的DAOc:(x)CommonDAO.java
  
  q是一个很多DAO都要l承到的通用DAOc,是我Ҏ(gu)实践ȝ出来的,Z(jin)减少幅Q这里只昄和本例相关的代码?br>  
  java代码:
  
  代码Q?br>  --------------------------------------------------------------------------------
  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;
  }
  }
  }
  
  q个cM要是通过子类传进来的先进l果集,取得查询的记录LQƈҎ(gu)据库q接q行单的理?br>  
  2Q、对数据库进行访问:(x)CertificateDAO.java
  
  java代码:
  
  代码Q?br>  --------------------------------------------------------------------------------
  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,"
  + "description,graduateID FROM TCertificate " ;
  pstmt = conn.prepareStatement(sql);
  rs = pstmt.executeQuery();
  /*Ҏ(gu)标进行处理,rsHandler Ҏ(gu)在父cDAO?/
  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.setDescription (rs.getString ("description")) ;
  certificateVO.setGraduateID (rs.getInt ("graduateID")) ;
  return certificateVO ;
  }
  catch (Exception ex)
  {
  ex.printStackTrace () ;
  return null ;
  }
  }
  }
  
  findCertificateList(int offset,int limit)是查得所有要昄的数据,q放入ArrayList中。看q网上有些例子,把数据记录放入ArrayList的动作过E直接在while循环体里完成Q如果字D多的话Q会(x)造成Ҏ(gu)q于宠大Q又不美观?q里Q数据记录放入ArrayList的动作过E由rs2VOҎ(gu)完成Q就比较整洁?jin)。另外,if (rs != null && rs.next ()) 配合while ( (countRows++ < limit) && rs.next ()) 是ؓ(f)?jin)程序的健壮性考虑的,E分析一下不隑־出结论?br>  
  3、徏立控制器lgQCertificateAction.java
  
  java代码:
  
  代码Q?br>  --------------------------------------------------------------------------------
  package com.xindeco.presentation;
  
  import javax.sql.* ;
  import java.util.* ;
  
  import javax.servlet.http.* ;
  import javax.servlet.* ;
  
  import org.apache.struts.action.* ;
  import org.apache.struts.util.* ;
  
  import com.xindeco.common.Pager;
  import com.xindeco.business.graduatedata.CertificateDAO ;
  
  public class CertificateAction
  extends Action
  {
  private static final int PAGE_LENGTH = 5 ; //每页昄5条记?br>  public ActionForward execute (ActionMapping mapping, Actionform form,
  HttpServletRequest request,
  HttpServletResponse response)
  {
  ActionForward myforward = null ;
  String myaction = mapping.getParameter () ;
  
  if (isCancelled (request))
  {
  return mapping.findForward ("failure") ;
  }
  if ("".equalsIgnoreCase (myaction))
  {
  myforward = mapping.findForward ("failure") ;
  }
  else if    ("LIST".equalsIgnoreCase (myaction))
  {
  myforward = performList (mapping, form, request, response) ;
  }
  else
  {
  myforward = mapping.findForward ("failure") ;
  }
  return myforward ;
  }
  
  private ActionForward performList (ActionMapping mapping,
  Actionform actionform,
  HttpServletRequest request,
  HttpServletResponse response)
  {
  try
  {
  DataSource ds = (DataSource) servlet.getServletContext().getAttribute(Action.DATA_SOURCE_KEY);
  
  CertificateDAO  certificateDAO = new CertificateDAO (ds) ;
  
  int offset = 0;  //页时的起始记录所在游?br>  int length = PAGE_LENGTH;
  String pageOffset = request.getParameter("pager.offset");
  if (pageOffset == null || pageOffset.equals("")) {
  offset = 0;
  } else {
  offset = Integer.parseInt(pageOffset);
  }
  List certificateList = certificateDAO .findCertificateList (offset,length) ;
  int size = certificateDAO.getRows(); // 取得总记录数
  String url = request.getContextPath()+"/"+mapping.getPath()+".do";
  String pagerHeader = Pager.generate(offset, size, length, url); //分页处理
  
  request.setAttribute ("pager", pagerHeader) ;
  request.setAttribute ("list", certificateList) ;
  }
  catch (Exception e)
  {
  e.printStackTrace();
  return mapping.findForward ("error") ;
  }
  return mapping.findForward ("success") ;
  }
  }
  
  CertificateAction.java主要是把数据从DAO中取出,q放入一个ArrayList 中,然后通过配置文g再Y件View的JSPc(din)?br>  
  5、徏立视图listcertificate.jsp文g?br>  
  jsp代码:
  
  代码Q?br>  --------------------------------------------------------------------------------
  
  <%@ page contentType="text/html; charset=GBK" %>
  <%@ taglib uri="/WEB-INF/struts-template.tld" prefix="template" %>
  <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
  <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
  <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
  
  <table bgcolor="#666666" cellpadding="1" cellspacing="0" border="0" width="500">
  <tr>
  <td>
  <table cellpadding="0" cellspacing="0" border="0" width="500">
  <tr>
  <td bgcolor="#fecc51">&</td>
  </tr>
  </table>
  </td>
  </tr>
  <tr>
  <td>
  <table cellpadding="0" cellspacing="0" border="0" width="500">
  <tr>
  <td bgcolor="#d6e0ed">
  &&<bean:message key="label.list4certificate"/>
  </td>
  </tr>
  <tr bgcolor="#FFFFFF">
  <td width="5%"></td><td width="19%"></td><td width="76%"></td>
  </tr>
  <tr>
  <td>
  <table bgcolor="#f2f2f2" width="500" cellspacing="0" border="0">
  <tr bgcolor="#bacce1">
  <td><b><bean:message key="Certificate.select"/> </b></td>
  <td><b><bean:message key="Certificate.certificateID"/> </b></td>
  <td><b><bean:message key="Certificate.certificateCode"/></b></td>
  <td><b><bean:message key="Certificate.certificateName"/></b></td>
  <td><b><bean:message key="Certificate.view"/></b></td>
  </tr>
  
  <bean:write name="pager" property="description"/>
  <logic:equal name="pager" property="hasPrevious" value="true">
  <a href="/graduatedata/list.do?viewPage=<bean:write name="pager" property="previousPage"/>" class="a02">
  Previous
  </a>
  </logic:equal>
  <logic:equal name="pager" property="hasNext" value="true">
  <a href="/graduatedata/list.do?viewPage=<bean:write name="pager" property="nextPage"/>" class="a02">
  Next
  </a>
  </logic:equal>
  
  <logic:notEmpty name="list" scope="request">
  <logic:iterate id="certificate" name="list" type="com.xindeco.business.graduatedata.CertificateVO"scope="request">
  <tr bgcolor="#FFFFFF">
  <td><html:text property="name" value="<bean:write name="certificate" property="certificateID" scope="page"/>"/>
  </td>
  <td> <bean:write name="certificate" property="certificateID" scope="page"/></td>
  <td> <bean:write name="certificate" property="certificateCode" scope="page"/></td>
  <td> <bean:write name="certificate" property="certificateName" scope="page"/></td>
  <td> <bean:write name="certificate" property="photoURL" scope="page"/></td>
  </tr>
  </logic:iterate>
  </logic:notEmpty>
  </table>
  </td>
  </tr>
  </table>
  </td>
  </tr>
  </table>
  
  6、对应的配置文gstruts-config.xml?br>  
  java代码:
  
  代码Q?br>  --------------------------------------------------------------------------------
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "
  <struts-config>
  <form-beans>
  <form-bean name="certificateform" type="com.xindeco.presentation.graduatedata.Certificateform" />
  </form-beans>
  <global-forwards>
  <forward name="error" path="/error/error.jsp" />
  </global-forwards>
  <action-mappings>
  <action name="certificateform" parameter="LIST" path="/graduatedata/list" scope="request" type="com.xindeco.presentation.graduatedata.CertificateAction" validate="true">
  <forward name="success" path="/graduatedata/listcertificate.jsp" />
  </action>
  </action-mappings>
  ……
  </struts-config>
  
  7、最后当然是最重要的分代码了(jin)QPager.java
  
  java代码:
  
  代码Q?br>  --------------------------------------------------------------------------------
  package com.xindeco.common;
  
  import java.util.* ;
  public class Pager {
  private static int MAX_PAGE_INDEX = 10; //脚昄多少?br>  private static String HEADER = "Result page";
  
  public static String generate(int offset, int length, int size, String url) {
  if (length > size) {
  String pref;
  if (url.indexOf("?") > -1) {
  pref = "&";
  } else {
  pref = "?";
  }
  String header = "<font face='Helvetica' size='-1'>"+HEADER+": ";
  if (offset > 0) {
  header += "&<a href=\""+url+pref+"pager.offset="+(offset-size)+"\">[<< Prev]</a>\n";
  }
  int start;
  int radius = MAX_PAGE_INDEX/2*size;
  if (offset < radius) {
  start = 0;
  } else if(offset < length-radius) {
  start = offset - radius;
  } else {
  start = (length/size-MAX_PAGE_INDEX)*size;
  }
  for(int i=start;i<length && i < start + MAX_PAGE_INDEX*size;i+=size) {
  if (i == offset) {
  header += "<b>"+(i/size+1)+"</b>\n";
  } else {
  header += "&<a href=\""+url+pref+"pager.offset="+i+"\">"+(i/size+1)+"</a>\n";
  }
  }
  if(offset < length - size) {
  header += "&<a href=\""+url+pref+"pager.offset="+((int)offset+(int)size)+"\">[Next >>]</a>\n";
  }
  header += "</font>";
  return header;
  } else {
  return "";
  }
  }
  }
  
  q部分代码的实现相当z,但已l够完成所需?jin)?



CoolYongZi 2007-08-01 16:11 发表评论
]]>
Javaq接C同数据库http://www.aygfsteel.com/wangyong/archive/2007/08/01/133819.htmlCoolYongZiCoolYongZiWed, 01 Aug 2007 08:02:00 GMThttp://www.aygfsteel.com/wangyong/archive/2007/08/01/133819.htmlhttp://www.aygfsteel.com/wangyong/comments/133819.htmlhttp://www.aygfsteel.com/wangyong/archive/2007/08/01/133819.html#Feedback0http://www.aygfsteel.com/wangyong/comments/commentRss/133819.htmlhttp://www.aygfsteel.com/wangyong/services/trackbacks/133819.html1、Oracle8/8i/9i数据库(thin模式Q?
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url="jdbc:oracle:thin:@localhost:1521:orcl";
//orcl为数据库的SID
String user="test";
String password="test";
Connection conn= DriverManager.getConnection(url,user,password);

2、DB2数据?
Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
String url="jdbc:db2://localhost:5000/sample";
//sampleZ的数据库?
String user="admin";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);

3、Sql Server7.0/2000数据?
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
String url="jdbc:microsoft:sqlserver://localhost:1433;databasename=pubs";
//mydb为数据库
String user="sa";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);

4、Sybase数据?
Class.forName("com.sybase.jdbc.SybDriver").newInstance();
String url =" jdbc:sybase:Tds:localhost:5007/myDB";
//myDBZ的数据库?
Properties sysProps = System.getProperties();
SysProps.put("user","userid");
SysProps.put("password","user_password");
Connection conn= DriverManager.getConnection(url, SysProps);

5、Informix数据?
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url =
"jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword";
//myDB为数据库?
Connection conn= DriverManager.getConnection(url);

6、MySQL数据?
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
//myDB为数据库?
Connection conn= DriverManager.getConnection(url);

7、PostgreSQL数据?
Class.forName("org.postgresql.Driver").newInstance();
String url ="jdbc:postgresql://localhost/myDB"
//myDB为数据库?
String user="myuser";
String password="mypassword";
Connection conn= DriverManager.getConnection(url,user,password);
8、access数据?br>con = DriverManager.getConnection("jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ=C:/data/Access/test1.mdb","dba","sql");

 



CoolYongZi 2007-08-01 16:02 发表评论
]]>
վ֩ģ壺 Ұ| | Ԫ| | ƽ| گ| | ɼ| | ۽| | ʦ| ɽ| | | | | | ɽ| Դ| ˱| | ˻| | | Դ| | ߴ| | ͨ| ˮ| ׿| | ɽ| | Ƽ| лͨ| | dz| μԴ| |