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

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

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

    風(fēng)行天下

    JAVA太極
    posts - 4, comments - 10, trackbacks - 0, articles - 55
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
    經(jīng)過(guò)前面的兩篇文章,我相信大家對(duì)Hibernate與Structs都有了初步的了解。 在Hibernate開(kāi)發(fā)指南之環(huán)境準(zhǔn)備中我們說(shuō)明了開(kāi)發(fā)Hibernate和Struts的工具環(huán)境的使用及相關(guān)原理,并寫(xiě)了一個(gè)簡(jiǎn)單的Hibernate的小例子。 在Hibernate開(kāi)發(fā)指南之Plugin to Struts中我們對(duì)Hibernate的SessionFactory的初始化與Struts結(jié)合的方法做了一些探討,讓大家對(duì)Struts的Plugin有了一定的理解,并且也仔細(xì)的了解了Hibernate的SesssionFactory的使用模式。 本文將進(jìn)入一個(gè)具有很強(qiáng)操作性的實(shí)例中來(lái),我們使用Struts的Action來(lái)通過(guò)Hibernate對(duì)數(shù)據(jù)庫(kù)進(jìn)行增、刪、改、查四項(xiàng)操作。 希望大家通過(guò)本文,來(lái)了解以下知識(shí): 

    Struts Action的使用及開(kāi)發(fā)方法/模式 
    Hibernate的數(shù)據(jù)庫(kù)增、刪、改、查的編寫(xiě)方法 
    Struts ActionForm Bean與Hibernate Maping Bean之間的轉(zhuǎn)換 
    Struts內(nèi)容的國(guó)際化 
    本文將不會(huì)涉及深入的Struts中的tag lib中的應(yīng)用,這方面的內(nèi)容大家可以參考技術(shù)天空的Chinese Struts項(xiàng)目中的相關(guān)文檔。 

    首先,請(qǐng)按照Hibernate開(kāi)發(fā)指南之環(huán)境準(zhǔn)備來(lái)準(zhǔn)備一個(gè)包含Hibernate和Struts的Web Project。 這個(gè)Web Project的名稱為:DBWebDemo。你可從這里下載這個(gè)空的Web Project,從這個(gè)項(xiàng)目來(lái)與我一起動(dòng)手開(kāi)始下面的工作。 你可以使用Eclipse的導(dǎo)入功能從zip文件中導(dǎo)入這個(gè)項(xiàng)目。 

    國(guó)際化資源文件
    首先我們?yōu)檎军c(diǎn)準(zhǔn)備一個(gè)國(guó)際化的資源文件,這個(gè)資源文件將是站點(diǎn)用戶所使用的語(yǔ)言來(lái)決定的,如果Struts不能找到相對(duì)應(yīng)的語(yǔ)言資源文件,就會(huì)使用默認(rèn)的資源文件。 這里我們先會(huì)建立一個(gè)txt文件,將所有的中文信息寫(xiě)入,再通過(guò)一個(gè)批處理或是shell腳本將該txt轉(zhuǎn)化成為Struts所使用的資源文件。這個(gè)方法并不是很好,但是我還不知在Eclipse中是否有更好的國(guó)際化插件。 如果你知道,請(qǐng)告訴我,我試用后會(huì)將相關(guān)的使用加入本節(jié)中。 

    建立原始的信息文件
    在DBWebDemo項(xiàng)目的WEB-INF文件夾中建立一個(gè)新的文件夾,名為res,并在其中建立一個(gè)新文件,名為res_zh.txt,同時(shí)新建一個(gè)批處理文件名為genres.bat和一個(gè)shell腳本文件名為genres.sh:


    這里我們給出genres.bat的內(nèi)容:

    native2ascii -encoding GBK C:\...\web\WEB-INF\res\res_zh.txt > C:\...\DBWebDemo\src\...\ApplicationResources_zh_CN.properties
        請(qǐng)使用你的文件的路徑來(lái)代替workspace之前的路徑。如果你有多種語(yǔ)言資源文件,加入多行,為每個(gè)文件準(zhǔn)備一個(gè)encode參數(shù),并使用該語(yǔ)言的后綴為ApplicationResources起名。

    設(shè)置站點(diǎn)所使用的語(yǔ)言
    我們使用一個(gè)Servlet的Filter來(lái)設(shè)置站點(diǎn)所使用的語(yǔ)言,我們可以將站點(diǎn)所使用的語(yǔ)言存在一個(gè)客戶端的cooke中,或是存于session中,還可以固定用戶必須使用中文。這里我們先固定用戶所使用的語(yǔ)言是中文。

    建立SetEncodeFilter類
    首先我們建立一個(gè)新的類名為SetEncodeFilter:


    Filter接口會(huì)要求實(shí)現(xiàn)類實(shí)現(xiàn)以下方法:

    init:初始化Filter時(shí)所做的工作 
    destroy:銷毀Filter時(shí)所做的工作 
    doFilter:當(dāng)有Servlet初調(diào)用時(shí)過(guò)濾的方法 
    我們先不寫(xiě)這三個(gè)方法,先將這個(gè)Filter配置到Web應(yīng)用中去。

    配置Web應(yīng)用使用Filter
    首先我們打開(kāi)web.xml,在web-app的內(nèi)容中加入filter的聲明:

     <filter>
      <filter-name>Set Web Application Character Encoding</filter-name>
      <filter-class> com.huangdong.dbwebdemo.SetEncodeFilter</filter-class>
      <init-param>
       <param-name>defaultencoding</param-name>
       <param-value>gb2312</param-value>
      </init-param>
     </filter>
        這里我們?cè)O(shè)置了過(guò)濾器的名稱和它的具體實(shí)現(xiàn)的類,還有就是為這個(gè)類配置了一個(gè)參數(shù),參數(shù)名為defaultencoding,它的值為gb2312。

    為了使用這個(gè)過(guò)濾器,我們還要設(shè)置過(guò)濾器的作用范圍,在filter的聲明后加入以下內(nèi)容:

     <filter-mapping>
      <filter-name>Set Web Application Character Encoding</filter-name>
      <url-pattern>/*</url-pattern>
     </filter-mapping>
        這里我們使用了/*這個(gè)通配符,意思是所有的servlet請(qǐng)求都會(huì)使用這個(gè)過(guò)濾器。接下來(lái),我們來(lái)書(shū)寫(xiě)filter的實(shí)現(xiàn)代碼。

    實(shí)現(xiàn)設(shè)置語(yǔ)言內(nèi)容過(guò)濾器
    以下是過(guò)濾器的代碼內(nèi)容:

    package com.huangdong.dbwebdemo;

    import java.io.IOException;

    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;

    /**
     * @author HD
     */
    public class SetEncodeFilter implements Filter {

     /**
      * 本過(guò)濾器的配置信息
      */
     protected FilterConfig filterConfig = null;

     /**
      * 系統(tǒng)缺省的語(yǔ)言編碼
      */
     protected String defaultencoding = null;

     /**
      * 初始化過(guò)濾器
      */
     public void init(FilterConfig filterConfig) throws ServletException {
      this.filterConfig = filterConfig;
      // 獲取系統(tǒng)缺省語(yǔ)言編碼
      this.defaultencoding = filterConfig.getInitParameter("defaultencoding");
     }

     /**
      * 過(guò)濾系統(tǒng)請(qǐng)求,設(shè)置請(qǐng)求的語(yǔ)言編碼
      */
     public void doFilter(
      ServletRequest request,
      ServletResponse response,
      FilterChain chain)
      throws IOException, ServletException {
      request.setCharacterEncoding(selectEncoding(request));
      chain.doFilter(request, response);

     }

     /**
      * 過(guò)濾器銷毀
      */
     public void destroy() {
      this.defaultencoding = null;
      this.filterConfig = null;
     }

     /**
      * 選擇這次過(guò)濾所使用的語(yǔ)言編碼
      * @param request 本次servlet請(qǐng)求的用戶request實(shí)例
      * @return 選擇出的語(yǔ)言編碼
      */
     protected String selectEncoding(ServletRequest request) {
      // 可以在這里加入從request中取得session并從session中獲取用戶所選擇的encode
      // 也可以在這里加入從request取得用戶客戶端的encode來(lái)設(shè)置當(dāng)前的語(yǔ)言編碼
      return (this.defaultencoding);
     }
    }

        代碼就不再一一解釋了,里面的注釋也說(shuō)的很清楚了。

    加入Hibernate的相關(guān)配置
    SessionFactory的初始化Struts Plugin
    具體的加入方法這里就不再說(shuō)明,請(qǐng)大家參考Hibernate開(kāi)發(fā)指南之Plugin to Struts中的說(shuō)明,這里只是列出代碼:

    package com.huangdong.dbwebdemo;

    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    import javax.servlet.ServletException;

    import net.sf.hibernate.HibernateException;
    import net.sf.hibernate.SessionFactory;
    import net.sf.hibernate.cfg.Configuration;

    import org.apache.struts.action.ActionServlet;
    import org.apache.struts.action.PlugIn;
    import org.apache.struts.config.ModuleConfig;

    /**
     * @author HD
     */
    public class InitHibernatePlugin implements PlugIn {

     /**
      * 插件所獲取的容器上下文實(shí)例
      */
     private Context ctx;
     /**
      * Hibernate初始化好的SessionFactory
      */
     private SessionFactory sessionFactory;

     /*
      * 插件銷毀方法
      */
     public void destroy() {
      if (ctx != null) {
       try {
        // unbind JNDI 節(jié)點(diǎn)
        ctx.unbind("HibernateSessionFactory");
       } catch (NamingException e) {
        e.printStackTrace();
       }
      }
      if (this.sessionFactory != null) {
       try {
        // 關(guān)閉sessionFactory
        sessionFactory.close();
       } catch (HibernateException e) {
        e.printStackTrace();
       }
       this.sessionFactory = null;
      }
     }

     /*
      * 插件初始化方法
      */
     public void init(ActionServlet servlet, ModuleConfig config)
      throws ServletException {
      try {
       // 獲取SessionFactory的實(shí)例
       this.sessionFactory =
        new Configuration().configure().buildSessionFactory();
      } catch (HibernateException ex) {
       throw new RuntimeException(
        "Exception building SessionFactory: " + ex.getMessage(),
        ex);
      }
      try {
       // 取得容器上下文
       ctx = new InitialContext();
       // 將sessionFactory bind到JND樹(shù)中
       ctx.bind("HibernateSessionFactory", this.sessionFactory);
      } catch (NamingException ex) {
       throw new RuntimeException(
        "Exception binding SessionFactory to JNDI: " + ex.getMessage(),
        ex);
      }
     }

    }
       session獲取工具類
    另外為了配置Plugin的使用,我們還是使用一個(gè)與HibernateUtilPlus相同功能的類名為DBUtil類,以下為它的代碼:

    package com.huangdong.dbwebdemo;

    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;

    import net.sf.hibernate.HibernateException;
    import net.sf.hibernate.Session;
    import net.sf.hibernate.SessionFactory;

    /**
     * @author HD
     */
    public class DBUtil {

     private static SessionFactory sessionFactory = null;
     public static final ThreadLocal session = new ThreadLocal();

     public static Session currentSession() throws HibernateException {
      if (sessionFactory == null) {
       // 如果sessionFactory實(shí)例為null則從JNDI中獲取
       if (getSystemSessionFactory() == false) {
        throw new HibernateException("Exception geting SessionFactory from JNDI ");
       }
      }
      Session s = (Session) session.get();
      if (s == null) {
       s = sessionFactory.openSession();
       session.set(s);
      }
      return s;
     }

     public static void closeSession() throws HibernateException {
      Session s = (Session) session.get();
      session.set(null);
      if (s != null)
       s.close();
     }
     
     private static boolean getSystemSessionFactory() {
      try {
       //從JNDI中取得SessionFactory的實(shí)例,如果出錯(cuò)返回false
       Context inttex = new InitialContext();
       sessionFactory =
        (SessionFactory) inttex.lookup("HibernateSessionFactory");
      } catch (NamingException e) {
       return false;
      }
      return true;
     }
    }
       Hibernate的配置文件
    不要忘記我們還要將Hibernate的配置文件寫(xiě)好(以下部分可以參見(jiàn)Hibernate開(kāi)發(fā)指南之環(huán)境準(zhǔn)備中相關(guān)的內(nèi)容):

    <?xml version='1.0' encoding='UTF-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC 
     "-//Hibernate/Hibernate Configuration DTD//EN" 
     "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">

    <hibernate-configuration>

        <session-factory>

            <property name="dialect">net.sf.hibernate.dialect.Oracle9Dialect</property>
            <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
            <property name="connection.username">hd</property>
            <property name="connection.password">abc</property>
            <property name="connection.url">jdbc:oracle:thin:@hdibm:1521:hdorc</property>
            
      <property name="connection.pool.size">1</property>
      <property name="statement_cache.size">25</property>
      <property name="jdbc.fetch_size">50</property>
      <property name="jdbc.batch_size">30</property>

      <property name="show_sql">true</property>
      
            <!-- Mapping files -->
            <mapping resource="com/huangdong/demo/dao/SysUser.hbm.xml"/>

        </session-factory>

    </hibernate-configuration>
       設(shè)置數(shù)據(jù)表實(shí)體化映射
    這里我們還是使用之前幾篇文章的Oracle數(shù)據(jù)庫(kù)。所以連接配置都是差不多的。我們這次的增、刪、改、查還是使用SYSUSER表,所以還是使用顯示原來(lái)的map文件。以下是SysUser類的源代碼:

    package com.huangdong.dbwebdemo.dao;

    import java.io.Serializable;
    import java.text.SimpleDateFormat;

    import org.apache.commons.lang.builder.EqualsBuilder;
    import org.apache.commons.lang.builder.HashCodeBuilder;
    import org.apache.commons.lang.builder.ToStringBuilder;

    /** @author Hibernate CodeGenerator */
    public class SysUser implements Serializable {

     /** identifier field */
     private String userid;

     /** persistent field */
     private String username;

     /** persistent field */
     private String userpasword;

     /** nullable persistent field */
     private java.util.Calendar lastlogin;

     /** full constructor */
     public SysUser(
      java.lang.String username,
      java.lang.String userpasword,
      java.util.Calendar lastlogin) {
      this.username = username;
      this.userpasword = userpasword;
      this.lastlogin = lastlogin;
     }

     /** default constructor */
     public SysUser() {
     }

     /** minimal constructor */
     public SysUser(java.lang.String username, java.lang.String userpasword) {
      this.username = username;
      this.userpasword = userpasword;
     }

     public java.lang.String getUserid() {
      return this.userid;
     }

     public void setUserid(java.lang.String userid) {
      this.userid = userid;
     }

     public java.lang.String getUsername() {
      return this.username;
     }

     public void setUsername(java.lang.String username) {
      this.username = username;
     }

     public java.lang.String getUserpasword() {
      return this.userpasword;
     }

     public void setUserpasword(java.lang.String userpasword) {
      this.userpasword = userpasword;
     }

     public java.util.Calendar getLastlogin() {
      return this.lastlogin;
     }

     public String getLastloginstr() {
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      return df.format(this.lastlogin);
     }

     public void setLastlogin(java.util.Calendar lastlogin) {
      this.lastlogin = lastlogin;
     }

     public String toString() {
      return new ToStringBuilder(this)
       .append("userid", getUserid())
       .toString();
     }

     public boolean equals(Object other) {
      if (!(other instanceof SysUser))
       return false;
      SysUser castOther = (SysUser) other;
      return new EqualsBuilder()
       .append(this.getUserid(), castOther.getUserid())
       .isEquals();
     }

     public int hashCode() {
      return new HashCodeBuilder().append(getUserid()).toHashCode();
     }

    }
        還有映射的xml文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
    <hibernate-mapping>
     <class name="com.huangdong.dbwebdemo.dao.SysUser" table="SYSUSER">
      <id column="userid" length="32" name="userid" type="string">
       <generator class="uuid.hex"/>
      </id>
      <property column="username" length="20" name="username" not-null="true" type="string" unique="true"/>
      <property column="userpasword" length="20" name="userpasword" not-null="true" type="string"/>
      <property column="lastlogin" length="7" name="lastlogin" type="calendar"/>
     </class>
    </hibernate-mapping>
        建立Struts的Action和Action FormBean
    建立FormBean
    在MyEclipse和Easy Struts中建立一個(gè)FormBean都是很簡(jiǎn)單的,首先打開(kāi)struts-config.xml文件,在大綱中選擇form-beans,新建:


    然后在表單中按下圖輸入:


    這樣我們就在com.huangdong.dbwebdemo.form包中新建了SysuserForm類。我們來(lái)為它加入相關(guān)的屬性,并設(shè)置geter和seter,以下是代碼:

    package com.huangdong.dbwebdemo.form;

    import org.apache.struts.action.ValidatorForm;

    public class SysuserForm extends ValidatorForm {

     // --------------------------------------------------------- Instance Variables
     /** 用戶ID,只讀 */
     private String userid;

     /** 用戶名 */
     private String username;

     /** 用戶密碼 */
     private String userpasword;

     /** 最后登錄時(shí)間 */
     private String lastlogin;
     
     public SysuserForm() {
      super();
     }

     public SysuserForm(SysUser sysuser) {
      this.newSysuserForm(
       sysuser.getUserid(),
       sysuser.getUsername(),
       sysuser.getUserpasword(),
       sysuser.getLastloginstr());
     }

     public SysuserForm(
      String userid,
      String username,
      String userpasword,
      String lastlogin) {
      this.newSysuserForm(userid, username, userpasword, lastlogin);
     }
     // --------------------------------------------------------- Methods
     /**
      * 為一個(gè)新的SysuserForm填充數(shù)據(jù)
      */
     private void newSysuserForm(
      String userid,
      String username,
      String userpasword,
      String lastlogin) {
      this.userid = userid;
      this.username = username;
      this.userpasword = userpasword;
      this.lastlogin = lastlogin;
     }
     /**
      * @return 最后登錄時(shí)間
      */
     public String getLastlogin() {
      return lastlogin;
     }

     /**
      * @return 用戶ID
      */
     public String getUserid() {
      return userid;
     }

     /**
      * @return 用戶名
      */
     public String getUsername() {
      return username;
     }

     /**
      * @return 用戶密碼
      */
     public String getUserpasword() {
      return userpasword;
     }

     /**
      * @param string 最后登錄時(shí)間,格式為YYYY-MM-DD hh:mm:ss
      */
     public void setLastlogin(String string) {
      lastlogin = string;
     }

     /**
      * @param string 用戶名
      */
     public void setUsername(String string) {
      username = string;
     }

     /**
      * @param string 用戶密碼
      */
     public void setUserpasword(String string) {
      userpasword = string;
     }
     /**
      * 對(duì)提交的表單進(jìn)行校驗(yàn)
      */
     public ActionErrors validate(ActionMapping mapping,
             HttpServletRequest request) {
      ActionErrors errors = super.validate(mapping, request);
      return errors;

     }
    }
        這里我們看到我們?cè)揊ormBean加入了數(shù)據(jù)校驗(yàn)的功能,在下面會(huì)仔細(xì)說(shuō)明。同時(shí)為了與Hibernate的數(shù)據(jù)庫(kù)進(jìn)行轉(zhuǎn)換加入了相關(guān)的構(gòu)造器和私有方法。

    建立第一個(gè)Action
    在struts-config.xml中加入action的定義,如下:

    <action  name="sysuserForm" 
       path="/sysuser" 
       type="com.huangdong.dbwebdemo.action.SysuserAction" 
       scope="request"
       input="/sysuser/editsysuser.jsp">
     <forward name="create" path="/sysuser/editsysuser.jsp"/>
    </action>
        這里我們來(lái)說(shuō)明一下,name和attribute說(shuō)明了本action所使用的FormBean的名稱, path指定了調(diào)用action的URL頭,type則指明了該action實(shí)現(xiàn)的具體類, scope說(shuō)明了FormBean所存活的區(qū)域,而input則說(shuō)明了輸入數(shù)據(jù)的View的地址(實(shí)質(zhì)上是校驗(yàn)有問(wèn)題里指到的View)。 在最后的forward定義中則定義了一系列的action可能會(huì)用到的View指向,這里我們只指定了一個(gè),后面會(huì)一個(gè)個(gè)的加入進(jìn)來(lái)。

    接著在com.huangdong.dbwebdemo.action包中新建SysuserAction類:

    package com.huangdong.dbwebdemo.action;

    import java.util.Locale;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.struts.action.Action;
    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;
    import org.apache.struts.util.MessageResources;

    import com.huangdong.dbwebdemo.form.SysuserForm;

    public class SysuserAction extends Action {

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

     // --------------------------------------------------------- Methods

     /** 
      * Method execute
      * @param ActionMapping mapping
      * @param ActionForm form
      * @param HttpServletRequest request
      * @param HttpServletResponse response
      * @return ActionForward
      * @throws Exception
      */
     public ActionForward execute(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception {

      // 初始化系統(tǒng)語(yǔ)言資源
      Locale locale = getLocale(request);
      MessageResources messages = getResources(request);
      // 本action默認(rèn)接收的處理請(qǐng)求為創(chuàng)建一個(gè)新的SYSUSER
      String action = "create";
      return (mapping.findForward(action));
     }
    }
        這里頭兩句代碼是用于設(shè)置View所使用的本地消息資源文件語(yǔ)言代碼的。

    將VO與PO關(guān)聯(lián)
    VO與PO的關(guān)系
    VO即業(yè)務(wù)層的數(shù)據(jù)表示,而PO即持久層的數(shù)據(jù)表示。VO會(huì)在View和業(yè)務(wù)處理時(shí)大量使用,也就是說(shuō),所有沒(méi)有入庫(kù)前的數(shù)據(jù)都會(huì)存儲(chǔ)于一個(gè)個(gè)的VO中。而PO則是數(shù)據(jù)庫(kù)在Java中的持久數(shù)據(jù)結(jié)構(gòu)。

    有許多人喜歡將Struts的VO與Hibernate的PO合并起來(lái),我不同意,原因很多,最重要的有以下幾點(diǎn):

    VO有自己的數(shù)據(jù)屬性,同時(shí)因框架的不同可能會(huì)有自己的結(jié)構(gòu)和方法,在Struts中我喜歡用FormBean來(lái)做VO,它就是擴(kuò)展ActionForm的一個(gè)類 
    VO中還會(huì)有大量的業(yè)務(wù)操作方法,如校驗(yàn)、自動(dòng)生成等方法 
    PO中會(huì)包含數(shù)據(jù)集之間的關(guān)系,如數(shù)據(jù)庫(kù)中的關(guān)系也會(huì)體現(xiàn)在PO中的一對(duì)一、多對(duì)多、一對(duì)多等,而在VO中不一定關(guān)注這樣的細(xì)節(jié) 
    總之,我更喜歡使用一個(gè)或多個(gè)關(guān)聯(lián)的類將業(yè)務(wù)邏輯中的VO與PO對(duì)映起來(lái),實(shí)現(xiàn)VO到PO的轉(zhuǎn)換,以及PO中VO的取出。

    VO與PO操作的抽像類
    所有VO到PO的操作基本上都會(huì)是持久層數(shù)據(jù)的存入或更改(刪除)。這樣的操作一定會(huì)涉及到數(shù)據(jù)庫(kù)的事務(wù)操作。另一方面,PO到VO的數(shù)據(jù)取出涉及到的則是數(shù)據(jù)集合的緩沖、分頁(yè)、過(guò)涉等技巧。所以我們?yōu)檫@兩種情況聲明兩個(gè)抽像類:

    AbsBaseMap類主要完成VO到PO的數(shù)據(jù)操作:

    package com.huangdong.dbwebdemo.db;

    import net.sf.hibernate.HibernateException;
    import net.sf.hibernate.Session;
    import net.sf.hibernate.Transaction;

    import com.huangdong.dbwebdemo.DBUtil;

    /**
     * 系統(tǒng)VO與PO的操作映射器抽像類,完成數(shù)據(jù)庫(kù)事務(wù)和連接的初始化以及數(shù)據(jù)庫(kù)事務(wù)的提交及數(shù)據(jù)庫(kù)連接的關(guān)閉
     * @author HD
     */
    public abstract class AbsBaseMap {
     // 數(shù)據(jù)庫(kù)連接session
     private Session session;
     // 數(shù)據(jù)庫(kù)事務(wù)處理器
     private Transaction transaction;

     /**
      * 初始化數(shù)據(jù)庫(kù)連接事務(wù)
      * @return 初始化完成的數(shù)據(jù)庫(kù)連接
      * @throws HibernateException
      */
     public Session beginTransaction() throws HibernateException {
      session = DBUtil.currentSession();
      transaction = session.beginTransaction();
      return session;
     }

     /**
      * 完成一個(gè)數(shù)據(jù)庫(kù)事務(wù)
      * @param commit 是否提交事務(wù),true時(shí)提交,false時(shí)向數(shù)據(jù)庫(kù)發(fā)起回滾(rollback)
      * @throws HibernateException
      */
     public void endTransaction(boolean commit) throws HibernateException {
      if (commit) {
       transaction.commit();
      } else {
       transaction.rollback();
      }
      DBUtil.closeSession();
     }
    }
        AbsQueryMap類則主要提供了有關(guān)持久層數(shù)據(jù)的查詢的抽像方法:

    package com.huangdong.dbwebdemo.db;

    /**
     * 系統(tǒng)VO與PO的查詢映射抽像類,加入查詢的分頁(yè)相關(guān)設(shè)置
     * @author HD
     */
    public class AbsQueryMap {
     /**
      * 數(shù)據(jù)庫(kù)連接session 
      **/
     Session session;

     // 分頁(yè)為20
     int pagesize = 20;
     // 當(dāng)前頁(yè)數(shù)
     int pageno = 1;

     /**
      * @return 分頁(yè)行數(shù)大小(默認(rèn)為20)
      */
     public int getPagesize() {
      return pagesize;
     }

     /**
      * @param i 設(shè)置分頁(yè)行數(shù)大小
      */
     public void setPagesize(int i) {
      pagesize = i;
     }
     /**
      * @return 返回當(dāng)前頁(yè)號(hào),初始值為1
      */
     public int getPageno() {
      return pageno;
     }

     /**
      * @param i 設(shè)置當(dāng)前頁(yè)號(hào)
      */
     public void setPageno(int i) {
      pageno = i;
     }

     /**
      * 設(shè)置查詢分頁(yè)
      */
     public void setQueryPage(Query query) {
      // 設(shè)置分頁(yè)起始記錄號(hào)
      query.setFirstResult((this.pageno - 1) * this.pagesize);
      // 設(shè)置頁(yè)內(nèi)數(shù)據(jù)量
      query.setMaxResults(this.pagesize);
     }

     /**
      * 打開(kāi)當(dāng)前的數(shù)據(jù)庫(kù)連接
      * @return
      * @throws HibernateException
      */
     public void initSession() throws HibernateException {
      this.session = DBUtil.currentSession();
     }

     /**
      * 關(guān)閉當(dāng)前的數(shù)據(jù)庫(kù)連接
      * @throws HibernateException
      */
     public void closeSession() throws HibernateException {
      DBUtil.closeSession();
     }
    }
        以后,我們所有的數(shù)據(jù)庫(kù)更新操作都會(huì)繼承AbsBaseMap類,而數(shù)據(jù)庫(kù)查詢操作會(huì)繼承AbsQueryMap類。

    數(shù)據(jù)庫(kù)增、刪、改操作映射
    一旦有了上節(jié)所提供的AbsBaseMap抽像類和Hibernate所提供的功能,我們只需要了解一點(diǎn)點(diǎn)Java的知識(shí)就可以完成復(fù)雜的數(shù)據(jù)庫(kù)更新功能了。

    首先在com.huangdong.dbwebdemo.db包中新建一個(gè)類名為SysUserMap并擴(kuò)展AbsBaseMap類:

    package com.huangdong.dbwebdemo.db;

    import com.huangdong.dbwebdemo.form.SysuserForm;

    public class SysUserMap extends AbsBaseMap {

    }
        先來(lái)實(shí)現(xiàn)一個(gè)增加的方法,在VO層,我們使用的數(shù)據(jù)類為SysuserForm,所以增加方法的參數(shù)一定是SysuserForm:

     public void createSysUser(SysuserForm sysuerForm)
      throws HibernateException {
      // 使用sysuerForm的相關(guān)屬性新建sysuser實(shí)例
      SysUser sysuser =
       new SysUser(
        sysuerForm.getUsername(),
        sysuerForm.getUserpasword(),
        Calendar.getInstance());
      // 啟動(dòng)事務(wù)
      Session session = this.beginTransaction();
      try {
       // 新增這個(gè)實(shí)例到數(shù)據(jù)庫(kù)中
       session.save(sysuser);
       // commit
       this.endTransaction(true);
      } catch (HibernateException e) {
       // rollback
       this.endTransaction(false);
       throw e;
      }
     }
        這個(gè)方法已經(jīng)非常的簡(jiǎn)單了,書(shū)寫(xiě)者完全可以不用理會(huì)數(shù)據(jù)庫(kù)相關(guān)的內(nèi)容了。

    接著我們來(lái)寫(xiě)更新的代碼,相比之下一樣的簡(jiǎn)單:

     /**
      * 更新一個(gè)sysuser
      * @param sysuerForm 包含更新內(nèi)容的sysuser form bean
      * @throws HibernateException
      */
     public void updateSysUser(SysuserForm sysuerForm)
      throws HibernateException {
      // 使用sysuerForm的相關(guān)屬性新建sysuser實(shí)例
      SysUser sysuser =
       new SysUser(
        sysuerForm.getUsername(),
        sysuerForm.getUserpasword(),
        Calendar.getInstance());
      // 啟動(dòng)事務(wù)
      Session session = this.beginTransaction();
      try {
       // 新增這個(gè)實(shí)例到數(shù)據(jù)庫(kù)中
       session.update(sysuser);
       // commit
       this.endTransaction(true);
      } catch (HibernateException e) {
       // rollback
       this.endTransaction(false);
      }
     }
        下面我們來(lái)寫(xiě)一個(gè)內(nèi)容更多一些的代碼--刪除。刪除一般都會(huì)是使用用戶ID來(lái)刪除,所以參數(shù)可以是帶有用戶ID的formbean或是用戶ID,我們使用兩個(gè)方法來(lái)實(shí)現(xiàn)刪除:

     /**
      * 依據(jù)一個(gè)sysuser formbean來(lái)刪除該用戶
      * @param sysuerForm 包含該用戶信息的Form Bean
      * @throws HibernateException
      */
     public void deleteSysUser(SysuserForm sysuerForm)
      throws HibernateException {
      String userid = sysuerForm.getUserid();
      this.deleteSysUser(userid);
     }
     
     /**
      * 依據(jù)用戶ID來(lái)刪除該用戶
      * @param userid 用戶ID
      * @throws HibernateException
      */
     public void deleteSysUser(String userid) throws HibernateException {
      Session session = this.beginTransaction();
      try {
       // 先向數(shù)據(jù)庫(kù)中查詢是否有這個(gè)用戶
       SysUser sysuser = (SysUser) session.load(SysUser.class, userid);
       // 干掉它!
       session.delete(sysuser);
       this.endTransaction(true);
      } catch (HibernateException e) {
       this.endTransaction(false);
      }
     }
        數(shù)據(jù)庫(kù)簡(jiǎn)單查詢
    數(shù)據(jù)庫(kù)的查詢相對(duì)復(fù)雜一些了,我們從簡(jiǎn)單做起,先不使用任何備件,查詢數(shù)據(jù)庫(kù)中所有的記錄。在com.huangdong.dbwebdemo.db中新建SysUserQueryMap類,它擴(kuò)展AbsQueryMap抽像類:

    package com.huangdong.dbwebdemo.db;

    import java.util.Iterator;

    import net.sf.hibernate.HibernateException;
    import net.sf.hibernate.Query;

    /**
     * @author HD
     */
    public class SysUserQueryMap extends AbsQueryMap {
     public SysUserQueryMap() throws HibernateException {
      this.initSession();
     }

     public Iterator findAllSysUser() throws HibernateException {
      // 查詢語(yǔ)句
      String querystr = "from SysUser";
      // 創(chuàng)建查詢
      Query query = this.session.createQuery(querystr);
      // 設(shè)置分頁(yè)
      this.setQueryPage(query);
      // 返回查詢出的結(jié)果集
      return query.iterate();
     }
    }
        這里我們已經(jīng)寫(xiě)好一個(gè)查詢所有的用戶的方法,它的第一句:

    String querystr = "from SysUser";
        這里的查詢語(yǔ)句使用了Hibernate的HQL語(yǔ)法,別的我們先不用管,這里SysUser是區(qū)分大小寫(xiě)的,我們之前定義了SysUser數(shù)據(jù)庫(kù)映射類,這里必須完全一樣,這樣Hibernate就會(huì)從數(shù)據(jù)庫(kù)中取出所有SysUser類的實(shí)例。

    接下來(lái)我們還需要一個(gè)方法能夠按照用戶的id返回其所對(duì)應(yīng)的用戶。 

     /**
      * 查詢出一個(gè)UserID的用戶實(shí)例
      * @param UserID 用戶的UserID
      * @return 用戶實(shí)例,如果數(shù)據(jù)庫(kù)無(wú)相應(yīng)記錄返回null
      * @throws HibernateException
      */
     public SysuserForm getSysuserByID(String UserID)
      throws HibernateException {
      SysuserForm sysuerform = null;

      try {
       sysuerform =
        new SysuserForm(
         (SysUser) this.session.load(SysUser.class, UserID));
      } catch (HibernateException e) {
       throw e;
      }
      return sysuerform;
     }     
        有了這個(gè)方法,我們才能對(duì)指定用戶進(jìn)行查詢,或者對(duì)他已有的信息進(jìn)行修改。 

    創(chuàng)建第一個(gè)View
    新建JSP頁(yè)面
    我們先為增加記錄建立一個(gè)JSP頁(yè)面,它提供了增加記錄的View。

      <head>
        <html:base />
        
        <title><bean:message key="title.register"/></title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">
        
      </head>
      
      <body>
       <logic:notEmpty name="sysuserForm" property="username" scope="request">
        <html:errors />
       </logic:notEmpty>
        <html:form action="/sysuser.do" method="post" focus="login" onsubmit="return validateSysuserForm(this);">
          <table border="0">
            <tr>
              <td>
               <bean:message key="prompt.login"/>
              </td>
              <td>
       <html:text property="username" size="16" maxlength="16"/>
              </td>
            </tr>
            <tr>
              <td>
               <bean:message key="prompt.password"/>
              </td>
              <td>
               <html:password property="userpasword" />
              </td>
            </tr>
            <logic:notEmpty name="sysuserForm" property="lastlogin" scope="request">
             <td>
              <html:hidden property="lastlogin" write="true"/>
             </td>
            </logic:notEmpty>
            <tr>
              <td colspan="2" align="center">
               <logic:empty name="sysuserForm" property="userid" scope="request">
                <input type="hidden" name="act" value="add"/>
               </logic:empty>
               <logic:notEmpty name="sysuserForm" property="userid" scope="request">
                <input type="hidden" name="act" value="update"/>
               </logic:notEmpty>
               <html:submit>
                <bean:message key="button.submit"/>
               </html:submit>
              </td>
            </tr>
          </table>
        </html:form>
        <html:javascript formName="sysuserForm"
            dynamicjavascript="true"
             staticjavascript="false"/>
        <script language="javascript1.1" src="../staticjavascript.jsp"/></script>
      </body>
    </html:html>
        有關(guān)這個(gè)JSP頁(yè)面中的各種taglib的使用在這里我們就不深入講解, 你可以到技術(shù)天空的Chinese Struts項(xiàng)目網(wǎng)站了解這些tag的使用。 我們只對(duì)一些我們關(guān)心的內(nèi)容做一些說(shuō)明。 

    首先我們使用了html:errors這個(gè)tag來(lái)顯示可能出現(xiàn)的錯(cuò)誤信息, 在后面我們的Action加工中我們會(huì)向errors中加入我們的數(shù)據(jù)校驗(yàn)、后臺(tái)操作產(chǎn)生的錯(cuò)誤,在這里通過(guò)這個(gè)tag來(lái)顯示出來(lái)。 這個(gè)表單的action="/sysuser.do"說(shuō)明提交還是提交到了sysuser這個(gè)action,因?yàn)榫唧w的增加方法也會(huì)是在這個(gè)action中完成。 表單的屬性最后有一個(gè)onsubmit="return validateSysuserForm(this);",是用于驗(yàn)證每個(gè)輸入條目的正確的,具體這里的定義我們會(huì)在稍后一些說(shuō)明。 在表單的最后我們使用logic這個(gè)tag來(lái)判斷sysuserForm中的userid是否存在,在確定表單中act這個(gè)參數(shù)的默認(rèn)值是add還是edit。 這么做的原因是我們還將使用這個(gè)jsp用于用戶信息的編輯。 在整個(gè)頁(yè)面的最后,我們使用了html:javascript這個(gè)tag將sysuserForm所使用到的校驗(yàn)javascript生成出來(lái)。 為了優(yōu)化資源的使用,我們將所有的校驗(yàn)javascript放在一個(gè)jsp中,也在最后使用javascript的引用標(biāo)簽引用進(jìn)來(lái)了。 

    View公用的校驗(yàn)javascript代碼頁(yè)
    下面我們列出staticjavascript.jsp的內(nèi)容:

    <%@ page language="java" %>
    <%-- set document type to javascript (addresses a bug in Netscape according to a web resource --%>
    <%@ page contentType="application/x-javascript" %>

    <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

    <html:javascript dynamicjavascript="false" staticjavascript="true"/>
        這個(gè)JSP則是使用了struts所帶的校驗(yàn)組件來(lái)生成了校驗(yàn)所使用的所有javascript

    將業(yè)務(wù)邏輯關(guān)聯(lián)起來(lái)
    為Action加入處理
    這個(gè)Action會(huì)處理的是與SYSUSER相關(guān)的所有操作,所以action會(huì)接收到的請(qǐng)求和顯示的表單會(huì)有多個(gè),我們?cè)趀xecute方法中加入以下的代碼:

      if (action.equals("create")) {
       // 如果處理請(qǐng)求類型為create
       request.setAttribute("sysuserForm", new SysuserForm());
       action = "create";
      } else if (action.equals("add")) {
       // 如果處理請(qǐng)求類型為add
       SysUserMap sysusermap = new SysUserMap();
       try {
        sysusermap.createSysUser(sysuser);
        // 加入成功,我們先再接著加下一個(gè)用戶
        request.setAttribute("sysuserForm", new SysuserForm());
        action = "create";
       } catch (HibernateException e) {
        // 數(shù)據(jù)庫(kù)存入出錯(cuò)
        ActionErrors errors = new ActionErrors();
        errors.add(
         ActionErrors.GLOBAL_ERROR,
         new ActionError("error.database.save", e.toString()));
        this.saveErrors(request, errors);
        //將當(dāng)前數(shù)據(jù)回顯,并顯示讓用戶重新輸入
        request.setAttribute("sysuserForm", sysuser);
        action = "create";
       }
        這個(gè)業(yè)務(wù)操作很簡(jiǎn)單,主要是調(diào)用Map來(lái)將VO的數(shù)據(jù)存入PO中,完成一個(gè)向數(shù)據(jù)庫(kù)中增加一條記錄的功能。 我們的具體實(shí)現(xiàn)是先創(chuàng)建了一個(gè)新的FormBean來(lái)存放用戶的輸入,之后將FormBean中的數(shù)據(jù)存入數(shù)據(jù)庫(kù)中。 在存入時(shí)如果出現(xiàn)錯(cuò)誤,我們將這個(gè)exception的內(nèi)容打入error中,在jsp中去顯示(可以回頭看看jsp中的內(nèi)容)。 

    接下來(lái),我們完成刪、改、查的功能,這些操作也是很簡(jiǎn)單的。 

      if (action == null || action.equals("list")) {
       //如果處理請(qǐng)求類型為list
       SysUserQueryMap sqm = new SysUserQueryMap();
       Iterator sysuserlist = sqm.findAllSysUser();
       request.setAttribute("sysuserlist", sysuserlist);
       action = "list";
      }    
        這段代碼定義了在默認(rèn)的情況下或者請(qǐng)求list操作的時(shí)候,完成列出所有用戶的操作。 實(shí)際就是調(diào)用了我們?cè)谇懊嫱瓿傻腟ysUserQueryMap中的findAllSysUser的方法從數(shù)據(jù)庫(kù)中取出了所有的用戶。 之后將用戶列表壓入了bean中。 

      if (action.equals("edit")) {
       // 請(qǐng)求類型為edit
       SysUserQueryMap sqm = new SysUserQueryMap();
       String uid = request.getParameter("userid");
       request.setAttribute("sysuserForm",sqm.getSysuserByID(uid));
      } else if (action.equals("update")){
       // 請(qǐng)求類型為update  
       SysUserMap sysusermap = new SysUserMap();
       sysusermap.updateSysUser(sysuser);
       action = "list";
      }
        這段代碼完成了編輯用戶數(shù)據(jù)的工作。我們可以看出首先需要完成一個(gè)edit工作, 這個(gè)操作的作用是從數(shù)據(jù)庫(kù)中取得這個(gè)用戶的信息,然后將這個(gè)用戶信息壓入FormBean中,供頁(yè)面進(jìn)行顯示。 在用戶對(duì)信息進(jìn)行更改之后則完成update操作,對(duì)數(shù)據(jù)庫(kù)條目進(jìn)行更新。 

      if (action.equals("delete")) {
       // 如果處理請(qǐng)求類型為delete
       SysUserMap sysusermap = new SysUserMap();
       String uid = request.getParameter("userid");
       try {
        sysusermap.deleteSysUser(uid);
       } catch (HibernateException e) {
        ActionErrors errors = new ActionErrors();
        errors.add(
         ActionErrors.GLOBAL_ERROR,
         new ActionError("error.database.delete", e.toString()));
        this.saveErrors(request, errors);
       }
       action = "list";
      }
        這段代碼完成刪除的功能。刪除指定的條目。如果出錯(cuò)就壓一個(gè)錯(cuò)誤到全局的錯(cuò)誤中。 

    對(duì)表單輸入的數(shù)據(jù)做校驗(yàn)
    在struts中帶有了Jakarta Commons中的一個(gè)叫做Validator的數(shù)據(jù)校驗(yàn)框架。 使用起來(lái)也是非常的簡(jiǎn)單。 

    首先將struts提供的validator-rules.xml的配置文件放入WEB-INF中。

    然后在struts-config.xml中加入validation的plugin聲明:

    <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
     <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
    </plug-in>
        我們會(huì)看到還有一個(gè)validator.xml文件不存在,在WEB-INF中新建這個(gè)xml文件,我們需要在其中加入自己的校驗(yàn)信息:

    <?xml version="1.0" encoding="ISO-8859-1" ?>

    <!DOCTYPE form-validation PUBLIC
              "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"
              "http://jakarta.apache.org/commons/dtds/validator_1_0.dtd">

    <form-validation>
        <formset>

            <form name="sysuserForm">

                <field property="username"
                        depends="required, minlength,maxlength">
                    <arg0   key="prompt.login"/>
                    <arg1   key="${var:minlength}" name="minlength"
                       resource="false"/>
                    <arg2   key="${var:maxlength}" name="maxlength"
                       resource="false"/>
                    <var>
                        <var-name>maxlength</var-name>
                        <var-value>16</var-value>
                    </var>
                    <var>
                        <var-name>minlength</var-name>
                        <var-value>3</var-value>
                    </var>
                </field>

                <field property="userpasword"
                        depends="required, minlength,maxlength">
                    <arg0   key="prompt.password"/>
                    <arg1   key="${var:minlength}" name="minlength"
                       resource="false"/>
                    <arg2   key="${var:maxlength}" name="maxlength"
                       resource="false"/>
                    <var>
                        <var-name>maxlength</var-name>
                        <var-value>16</var-value>
                    </var>
                    <var>
                        <var-name>minlength</var-name>
                        <var-value>3</var-value>
                    </var>
                </field>

            </form>
        </formset>
    </form-validation>
        仔細(xì)的看看這個(gè)xml文件的內(nèi)容就會(huì)發(fā)現(xiàn)它說(shuō)明要校驗(yàn)的表單名為sysuserForm, 并對(duì)這個(gè)表單中的幾個(gè)需要做校驗(yàn)的字段一一做了校驗(yàn)方法說(shuō)明。 具體Validator的使用請(qǐng)參考它帶的相關(guān)文檔和struts的相關(guān)說(shuō)明。 

    注意:如果使用默認(rèn)的檢查規(guī)則對(duì)表單進(jìn)行檢查的話需要注意幾個(gè)關(guān)鍵的地方,否則你可能就會(huì)花很長(zhǎng)的時(shí)間檢查js腳本無(wú)法應(yīng)用的原因。 首先您所使用的FormBean就不能是原來(lái)的ActionForm了,需要更改為ValidatorForm。 這個(gè)Form中還必須有一個(gè)類似這樣的validate方法: 

        public ActionErrors validate(
      ActionMapping mapping,
      HttpServletRequest request) {
      ActionErrors errors = super.validate(mapping, request);
      return errors;

     }
        其次需要在頁(yè)面的結(jié)尾處聲明使用javascript: 

         
             <html:javascript formName="sysuserForm"
            dynamicjavascript="true"
             staticjavascript="false"/>
         
        dynamicjavascript屬性是代表是否在頁(yè)面內(nèi)生成動(dòng)態(tài)的js腳本。 如果您要對(duì)表單進(jìn)行合法性檢查的話,此屬性必須為true。 staticjavascript屬性代表是否在頁(yè)面內(nèi)生成靜態(tài)js腳本。 如果您設(shè)為true,則存放在validator-rules.xml文件中的規(guī)則檢查js 都將填充到本頁(yè)面內(nèi)。這樣做的效果不是很好,因?yàn)闀?huì)使頁(yè)面變得很大, 并且消耗大量的額外資源。通常的做法是將此選項(xiàng)設(shè)置成false, 將validator-rules.xml中的js填充到一個(gè)指定的jsp頁(yè)面中去。 這樣多個(gè)表單都可以同時(shí)使用一個(gè)靜態(tài)頁(yè)面,從而節(jié)省大量的資源。 如果這樣做我們就需要在后面在聲明對(duì)這個(gè)靜態(tài)頁(yè)面進(jìn)行引用。 

         
             <script language="javascript1.1" src="../staticjavascript.jsp"/></script>
             
        書(shū)寫(xiě)這句話的時(shí)候也需要注意一點(diǎn),盡量使用相對(duì)路徑較好。 使用絕對(duì)路徑的時(shí)候很難準(zhǔn)確的定位這個(gè)靜態(tài)頁(yè)面的位置。 

    最后需要注意的一點(diǎn)就是在引用這個(gè)js檢查的時(shí)候。 

         
             <html:form action="/sysuser.do" method="post" focus="login" onsubmit="return validateSysuserForm(this);">
         
        return validateSysuserForm(this);這個(gè)函數(shù)的名字是根據(jù)你所檢查的表單的名字而改變的。 例如我們檢查的這個(gè)表單叫做sysuserForm,則生成的檢查函數(shù)的名字為validateSysuserForm。 您在使用的時(shí)候需要將其修改成跟您所需要檢查的表單相對(duì)應(yīng)的函數(shù)名,否則js的檢查就形同虛設(shè)了。 

    附錄
    最后我們提供我們這篇文章所使用的例子的完整項(xiàng)目給大家下載。 您可以方便的將這個(gè)項(xiàng)目導(dǎo)入到您的eclipse中去。 

    轉(zhuǎn)自http://bsd.huangdong.com/dev/hibernate/strutsaction/index.html


    評(píng)論

    # re: 使用Struts的Action來(lái)通過(guò)Hibernate對(duì)數(shù)據(jù)庫(kù)進(jìn)行增、刪、改、查四項(xiàng)操作  回復(fù)  更多評(píng)論   

    2011-07-29 23:24 by Codenfans
    謝謝 可以。。。了

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲欧美日韩中文字幕一区二区三区 | 亚洲中文久久精品无码ww16| 国产亚洲精品免费视频播放 | 久久久免费精品re6| 日韩一级视频免费观看| 亚洲乱码日产一区三区| 亚洲熟妇无码av另类vr影视| 三年片免费观看大全国语| 无码国产精品一区二区免费| 久久久青草青青国产亚洲免观| 美女又黄又免费的视频| 国产福利在线免费| 亚洲av无码av制服另类专区| 亚洲AV无码精品国产成人| 99re免费视频| 亚洲视频在线观看免费视频| 国产精品免费久久久久久久久 | 永久免费视频网站在线观看| 国产亚洲午夜高清国产拍精品| 丁香六月婷婷精品免费观看| 在线观看无码的免费网站| 久久亚洲精品成人AV| 黄色视屏在线免费播放| 国产精品久久免费视频| 色偷偷女男人的天堂亚洲网| 香蕉免费一区二区三区| 亚洲爽爽一区二区三区| 亚洲AV成人一区二区三区观看| 免费乱理伦在线播放| 亚洲av无码片vr一区二区三区| 免费国产一级特黄久久| 国产免费一区二区三区免费视频| 亚洲av中文无码乱人伦在线r▽| **毛片免费观看久久精品| 精品亚洲成在人线AV无码| 久久久免费观成人影院| 中文字幕亚洲精品资源网| 日韩高清在线高清免费| 中文字幕免费在线播放| 亚洲fuli在线观看| 亚洲国产中文v高清在线观看|