風(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)原理,并寫了一個(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ù)增、刪、改、查的編寫方法 
          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文件,將所有的中文信息寫入,再通過(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ò)濾的方法 
          我們先不寫這三個(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)書寫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的配置文件寫好(以下部分可以參見(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)單了,書寫者完全可以不用理會(huì)數(shù)據(jù)庫(kù)相關(guān)的內(nèi)容了。

          接著我們來(lái)寫更新的代碼,相比之下一樣的簡(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)寫一個(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)寫好一個(gè)查詢所有的用戶的方法,它的第一句:

          String querystr = "from SysUser";
              這里的查詢語(yǔ)句使用了Hibernate的HQL語(yǔ)法,別的我們先不用管,這里SysUser是區(qū)分大小寫的,我們之前定義了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í)候也需要注意一點(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)航:
           
          主站蜘蛛池模板: 衡山县| 徐水县| 新乐市| 仁化县| 南乐县| 通榆县| 饶平县| 兴安盟| 郧西县| 天气| 新郑市| 新龙县| 高清| 北流市| 璧山县| 德格县| 五峰| 柏乡县| 湾仔区| 辽阳市| 新竹市| 藁城市| 广汉市| 商水县| 香港| 辽阳市| 潞西市| 三明市| 托里县| 乳山市| 宝坻区| 宝应县| 大渡口区| 织金县| 宕昌县| 临猗县| 武平县| 金寨县| 孟州市| 洛宁县| 正阳县|