Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 285|回复: 0

[struts学习]又一个Hibernate+Struts例子

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-11 00:57:00 | 显示全部楼层 |阅读模式
    学习笔记:Hibernate开发指南之Struts Action实践  

        在网上看到一篇文章《Hibernate开发指南之Struts Action实践 》这是一个入门实例,使用Struts的Action通过Hibernate对数据库进行增、删、改、查四项操作,还有表单的服务器端和客户端验证。 可惜没有下到全部的源文件,便自已动手加、改,不当之处难免,权当参考。

    一、准备工作
         主要是搭建Hibernate+Struts的环境,我是mysql+Tomcat 5.0+Hibernate2.1+Struts1.2.4,包括建目录和复制jar文件到相关目录,还有在mysql中创建数据库HibernateTest和表sysuser,请下载我的目录结构参考。
    下面文件createTable.txt用来创建表sysuser

      

      
      create table sysuser(
      userid varchar(32) not null,
      username  varchar(20) not null unique,
      userpasword varchar(20) not null,
      lastlogin DATETIME,
      primary key(userid)
    )

    二、Hibernate的配置文件hibernate.cfg.xml,主要是数据库的设定,这里用mysql。

    <?xml version=&#391;.0" encoding="big5"?>
    <!DOCTYPE hibernate-configuration
         PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
         "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
      
      
       
       
       

       
      

    <hibernate-configuration>
         <session-factory>
             <!-- 显示实际操作数据库时的SQL -->
             <property name="show_sql">true</property>
             <!-- SQL方言,这边设定的是MySQL -->
             <property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
             <!-- JDBC驱动程序 -->
             <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
             <!-- JDBC URL -->
             <property name="connection.url">jdbc:mysql://localhost/HibernateTest</property>
             <!-- 数据库使用者 -->
             <property name="connection.username">root</property>
             <!-- 数据库密码 -->
             <property name="connection.password"></property>

             <!-- 对象与数据库表格映像文件 -->
             <mapping resource="com/huangdong/dbwebdemo/dao/SysUser.hbm.xml"/>

         </session-factory>
    </hibernate-configuration>


    二、Struts的配置文件struts-config.xml,有表单定义,动作映射和资源文件,插件定义。
    <?xml version="1.0" encoding="iso-8859-1"?>
    <!DOCTYPE struts-config PUBLIC
               "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
               "http://struts.apache.org/dtds/struts-config_1_2.dtd">

    <struts-config>

         <form-beans>
             <form-bean name="sysuserForm" type="com.huangdong.dbwebdemo.form.SysuserForm"/>
         </form-beans>

       <action-mappings>      
              <action  name="sysuserForm"  
              path="/sysuser"  
              type="com.huangdong.dbwebdemo.action.AddAction"  
              scope="request"
                      validate="true"
              input="/sysuser/editsysuser.jsp">
                  <forward name="add" path="/sysuser/add.jsp" />
              </action>

              <action path="/list"  
                      type="com.huangdong.dbwebdemo.action.ListAction"  
              scope="request"
                      input="/sysuser/index.jsp">
                      <forward name="list" path="/sysuser/list.jsp" />
              </action>  
          
              <action  path="/edit"  
                       type="com.huangdong.dbwebdemo.action.EditAction"  
               scope="request"
                       input="/sysuser/editsysuser1.jsp">
                       <forward name="edit" path="/sysuser/editsysuser1.jsp" />                  
                       <forward name="err1" path="/sysuser/err1.jsp" />


             </action>  
              <action  path="/del"  
                       type="com.huangdong.dbwebdemo.action.DelAction"  
               scope="request"
                          input="/sysuser/del.jsp">
                       <forward name="del" path="/sysuser/delok.jsp" />
                       <forward name="err" path="/sysuser/err.jsp" />

             </action>
             <action   name="sysuserForm"  
                       path="/update"  
                       type="com.huangdong.dbwebdemo.action.UpdateAction"  
               scope="request"
                          input="/sysuser/editsysuser1.jsp">
                       <forward name="updateok" path="/sysuser/updateok.jsp" />
                     
             </action>
       
         </action-mappings>
          
         <message-resources parameter="resources.application"/>  

         <plug-in className="com.huangdong.dbwebdemo.InitHibernatePlugin" />
          <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
         <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
          </plug-in>
    </struts-config>

         这里加了两个插件,其一利用Plugin的方式将Hibernate与Struts结合起来,其二进行服务器端验证。插件将在Web应用启动时初始化。
         在InitHibernatePlugin.java的init()方法中将SessionFactory的实例bind到JNDI目录树的一个节点上,以便在所有要使用SessionFactory的地方通过JNDI lookup出sessionFactory的实例得到具体的session进行数据库操作。
    InitHibernatePlugin.java(部分)
              /*
          * 插件初始化方法
          */
         public void init(ActionServlet servlet, ModuleConfig config)
             throws ServletException {
             try {
                 // 获取SessionFactory的实例
                 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树中
                 ctx.bind("HibernateSessionFactory", this.sessionFactory);
             } catch (NamingException ex) {
                 throw new RuntimeException(
                     "Exception binding SessionFactory to JNDI: " + ex.getMessage(),
                     ex);
             }
         }

    二、国际化资源文件
        我们为站点准备一个国际化的资源文件,这个资源文件将是站点用户所使用的语言来决定的,如果Struts不能找到相对应的语言资源文件,就会使用默认的资源文件。 这里我们先会建立一个txt文件,将所有的中文信息写入,再通过一个批处理或是shell脚本将该txt转化成为Struts所使用的资源文件。

    这里我们给出genres.bat的内容:

    native2ascii -encoding GBK d:java
    es_zh.txt >d:javaapplication_zh_CN.properties
                      
                      
    请使用你的文件的路径来代替这里的路径。下面是res_zh.txt:
    # Resources for parameter "ApplicationResources"
    # Project P/WebDlog
    title.register=用户注册
    prompt.login=用户名
    prompt.password=口令

    # Errors
    errors.footer=
    errors.header=<h3><font color="red">验证错误</font></h3>你必须更正下列错误:
    errors.ioException=I/O exception rendering error messages: {0}
    error.database.missing=<li>User database is missing, cannot validate logon credentials</li>
    errors.required={0} 是必填项.
    errors.minlength={0} 不能少于 {1} 个字符.
    errors.maxlength={0} 不能大于 {2} 个字符.
    errors.invalid={0} 是无效的.

    errors.byte={0} must be an byte.
    errors.short={0} must be an short.
    errors.integer={0} must be an integer.
    errors.long={0} must be an long.
    errors.float={0} must be an float.
    errors.double={0} must be an double.

    errors.date={0} is not a date.

    errors.range={0} is not in the range {1} through {2}.

    errors.creditcard={0} is not a valid credit card number.

    errors.email={0} is an invalid e-mail address.



    三、设置站点所使用的语言
          我们使用一个Servlet的Filter来设置站点所使用的语言。(略,请参看原文)

    四、session获取工具类
         另外为了配置Plugin的使用,我们使用工具类DBUtil类来获取Session,以下为它的代码:

    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实例为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的实例,如果出错返回false
                 Context inttex = new InitialContext();
                 sessionFactory =
                     (SessionFactory) inttex.lookup("HibernateSessionFactory");
             } catch (NamingException e) {
                 return false;
             }
             return true;
         }
    }
                  
    五、持久层的数据表示及设置数据表实体化映射
        我们的增、删、改、查使用sysuser表,以下是其对应的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.demo.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
       
    有AddAction.java,UpdateAction.java,SysuserForm.java等,请下载源码查看。

    七、将VO与PO关联
    VO与PO的关系
        VO即业务层的数据表示,而PO即持久层的数据表示,在这个例子里就是SysUser.java类。VO会在View和业务处理时大量使用,也就是说,所有没有入库前的数据都会存储于一个个的VO中。而PO则是数据库在Java中的持久数据结构。

    有许多人喜欢将Struts的VO与Hibernate的PO合并起来,我不同意,原因很多,最重要的有以下几点:

    1、VO有自己的数据属性,同时因框架的不同可能会有自己的结构和方法,在Struts中我喜欢用FormBean来做VO,它就是扩展ActionForm的一个类  

    2、VO中还会有大量的业务操作方法,如校验、自动生成等方法  
    3、PO中会包含数据集之间的关系,如数据库中的关系也会体现在PO中的一对一、多对多、一对多等,而在VO中不一定关注这样的细节  

    总之,我更喜欢使用一个或多个关联的类将业务逻辑中的VO与PO对映起来,实现VO到PO的转换,以及PO中VO的取出。

    九、VO与PO操作的抽像类
          所有VO到PO的操作基本上都会是持久层数据的存入或更改(删除)。这样的操作一定会涉及到数据库的事务操作。另一方面,PO到VO的数据取出涉及到的则是数据集合的缓冲、分页、过涉等技巧。所以我们为这两种情况声明两个抽像类:

    AbsBaseMap类主要完成VO到PO的数据操作:

    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;

    /**
      * 系统VO与PO的操作映射器抽像类,完成数据库事务和连接的初始化以及数据库事务的提交及数据库连接的关闭
      * @author HD
      */
    public abstract class AbsBaseMap {
         // 数据库连接session
         private Session session;
         // 数据库事务处理器
         private Transaction transaction;

         /**
          * 初始化数据库连接事务
          * @return 初始化完成的数据库连接
          * @throws HibernateException
          */
         public Session beginTransaction() throws HibernateException {
             session = DBUtil.currentSession();
             transaction = session.beginTransaction();
             return session;
         }

         /**
          * 完成一个数据库事务
          * @param commit 是否提交事务,true时提交,false时向数据库发起回滚(rollback)
          * @throws HibernateException
          */
         public void endTransaction(boolean commit) throws HibernateException {
             if (commit) {
                 transaction.commit();
             } else {
                 transaction.rollback();
             }
             DBUtil.closeSession();
         }
    }
                      
    AbsQueryMap类则主要提供了有关持久层数据的查询的抽像方法:

    package com.huangdong.dbwebdemo.db;

    /**
      * 系统VO与PO的查询映射抽像类,加入查询的分页相关设置
      * @author HD
      */
    public class AbsQueryMap {
         /**
          * 数据库连接session  
          **/
         Session session;

         // 分页为20
         int pagesize = 20;
         // 当前页数
         int pageno = 1;

         /**
          * @return 分页行数大小(默认为20)
          */
         public int getPagesize() {
             return pagesize;
         }

         /**
          * @param i 设置分页行数大小
          */
         public void setPagesize(int i) {
             pagesize = i;
         }
         /**
          * @return 返回当前页号,初始值为1
          */
         public int getPageno() {
             return pageno;
         }

         /**
          * @param i 设置当前页号
          */
         public void setPageno(int i) {
             pageno = i;
         }

         /**
          * 设置查询分页
          */
         public void setQueryPage(Query query) {
             // 设置分页起始记录号
             query.setFirstResult((this.pageno - 1) * this.pagesize);
             // 设置页内数据量
             query.setMaxResults(this.pagesize);
         }

         /**
          * 打开当前的数据库连接
          * @return
          * @throws HibernateException
          */
         public void initSession() throws HibernateException {
             this.session = DBUtil.currentSession();
         }

         /**
          * 关闭当前的数据库连接
          * @throws HibernateException
          */
         public void closeSession() throws HibernateException {
             DBUtil.closeSession();
         }
    }
                      
    以后,我们所有的数据库更新操作都会继承AbsBaseMap类,而数据库查询操作会继承AbsQueryMap类。

    十、数据库增、删、改操作映射
         一旦有了上节所提供的AbsBaseMap抽像类和Hibernate所提供的功能,我们只需要了解一点点Java的知识就可以完成复杂的数据库更新功能了。

        首先在com.huangdong.dbwebdemo.db包中新建一个类名为SysUserMap并扩展AbsBaseMap类:

    package com.huangdong.dbwebdemo.db;

    import com.huangdong.dbwebdemo.form.SysuserForm;

    public class SysUserMap extends AbsBaseMap {

    }
                      
         先来实现一个增加的方法,在VO层,我们使用的数据类为SysuserForm,所以增加方法的参数一定是SysuserForm:

         public void createSysUser(SysuserForm sysuerForm)
             throws HibernateException {
             // 使用sysuerForm的相关属性新建sysuser实例
             SysUser sysuser =
                 new SysUser(
                     sysuerForm.getUsername(),
                     sysuerForm.getUserpasword(),
                     Calendar.getInstance());
             // 启动事务
             Session session = this.beginTransaction();
             try {
                 // 新增这个实例到数据库中
                 session.save(sysuser);
                 // commit
                 this.endTransaction(true);
             } catch (HibernateException e) {
                 // rollback
                 this.endTransaction(false);
                 throw e;
             }
         }
                      
    这个方法已经非常的简单了,书写者完全可以不用理会数据库相关的内容了。
    其它代码请下载。
          
    十二、数据库简单查询
         数据库的查询相对复杂一些了,我们从简单做起,先不使用任何条件,查询数据库中所有的记录。在com.huangdong.dbwebdemo.db中新建SysUserQueryMap类,它扩展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 {
             // 查询语句
             String querystr = "from SysUser";
             // 创建查询
             Query query = this.session.createQuery(querystr);
             // 设置分页
             this.setQueryPage(query);
             // 返回查询出的结果集
             return query.iterate();
         }
    }
                      
    这里我们已经写好一个查询所有的用户的方法,它的第一句:

    String querystr = "from SysUser";
                      
    这里的查询语句使用了Hibernate的HQL语法,别的我们先不用管,这里SysUser是区分大小写的,我们之前定义了SysUser数据库映射类,这里必须完全一样,这样Hibernate就会从数据库中取出所有SysUser类的实例。

    接下来我们还需要一个方法能够按照用户的id返回其所对应的用户。  

         /**
          * 查询出一个UserID的用户实例
          * @param UserID 用户的UserID
          * @return 用户实例,如果数据库无相应记录返回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;
         }                     
                      
    有了这个方法,我们才能对指定用户进行查询,或者对他已有的信息进行修改。  

    十一、创建第一个View
    新建JSP页面
    我们先为增加记录建立一个JSP页面editsysuser.jsp,它提供了增加记录的View。

       <%@ page contentType="text/HTML;charset=UTF-8" %>  
    <%@ taglib uri="/tags/struts-bean" prefix="bean" %>  
    <%@ taglib uri="/tags/struts-html" prefix="html" %>  
    <%@ taglib uri="/tags/struts-logic" prefix="logic" %>  
    <html:html>  
    <head>
          
         <title><bean:message key="title.register"/></title>
         <html:base />
             
       </head>
       
       <body>
    <br>OK!!!<br>
      <logic:messagesPresent>
               <bean:message key="errors.header"/>
               <ul>
               <html:messages id="error">
                <li><bean:write name="error"/></li>
              </html:messages>
              </ul><hr />
    </logic:messagesPresent>


         <html:form action="/sysuser.do?action=add" method="post" focus="username" onsubmit="return validateSysuserForm(this);">
           <table border="0">
             <tr>
               <td>
                   <bean:message key="prompt.login"/>
               </td>
               <td>
             <html:text property="username" size="16" maxlength="20"/>
               </td>
             </tr>
             <tr>
               <td>
                     <bean:message key="prompt.password"/>
               </td>
               <td>
                     <html:password property="userpasword" />
               </td>
             </tr>
             
             <tr>
               <td>
                     <html:submit>
                        <bean:message key="title.register"/>
                     </html:submit>
                </td>
             </tr>
           </table>

         </html:form>
        <html:javascript formName="sysuserForm"/>
       </body>
    </html:html>
                      
    十二、客户端验证和服务器端验证
         editsysuser.jsp中的表单属性中有一个onsubmit="return validateSysuserForm(this);"与页面最后的<html:javascript formName="sysuserForm"/>一起构成表单客户端验证。所有javaScript验证代码Struts自动生成。
         表单服务器端验证由struts-config.xml中的插件
      <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
         <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
      </plug-in>
        及资源文件构成。

    十三、将业务逻辑关联起来
    所有的Action类请下载。

      

      
      
       
       

         
       

         
       
      



    源码下载:http://file.javaxxz.com/2014/10/11/005659765.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-26 13:14 , Processed in 0.399939 second(s), 50 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表