別的請參考:http://www.java3z.com/cwbwebhome/article/article2a/2101.jsp?id=365
http://blogger.org.cn/blog/more.asp?name=jjs_love&id=12738
http://willsu.cnblogs.com/archive/2006/03/26/172459.html
一、準備工作
????主要是搭建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=?.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\res_zh.txt?>d:\java\application_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?分頁行數大?。J為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>
???及資源文件構成。
十三、將業務邏輯關聯起來
posted on 2006-06-05 17:44
船長 閱讀(483)
評論(0) 編輯 收藏 所屬分類:
J2EE