Foreword
After two articles, I believe that everyone has a preliminary understanding of Hibernate and Structs. In the environment of Hibernate Development Guide, we explained the use and related principles of the development of Hibernate and Struts, and wrote a simple Hibernate small example. In the Plugin to Struts of Hibernate Development Guide, we made some discussions in the initialization of Hibernate's sessionFactory, let everyone have a certain understanding of Struts's Plugin, and also understand the use model of Hibernate's sessionFactory. . This article will enter an example with strong operability, we use the Struts Action to increase, delete, change, and check four operations for the database via Hibernate. I hope that you will learn about the following knowledge through this article:
Struts Action and Development Method / Mode Hibernate's Database Increase, Delete, Change, Strike Struts Actionform Bean and Hibernate Maping Bean Internationalization The Internationalization of Struts Content This article will not involve Tag LIB in in-depth Struts The application, this content can be referred to the related documentation in the CHINESE STRUTS project of the technology sky.
First, please prepare a Web Project that contains Hibernate and Struts in accordance with the environment of the Hibernate Development Guide. The name of this Web Project is: dbwebdemo. You can download this empty Web Project from here, from this project to start the following work together. You can import this project from the ZIP file using the Eclipse import function.
Internationalized resource documents First we prepare an international resource document for the site. This resource file will be the language used by the site user. If Struts cannot find a corresponding language resource file, the default resource file will be used. Here we will build a TXT file first, write all Chinese information, and turn the TXT to the resource file used by Struts by a batch or shell script. This method is not very good, but I still don't know if there is a better international plugin in Eclipse. If you know, please tell me that I will add the associated use after I tried it.
Create a new folder in the Web-INF folder of the DBWebDemo project, named RES, and establish a new file in it, named res_zh.txt, and create a batch file name GenRES. Bat and a shell script file named genres.sh:
Here we give GenRes.bat content:
Native2ascii -Encoding GBK C: /.../ Web / Web-INF / RES / RES_ZH.TXT> C: /.../ dbwebdemo / src /.../ ApplicationResources_zh_cn.properties Please use your file path to replace The path before Workspace. If you have multiple language resource files, add multiple rows, prepare an Encode parameter for each file, and use the suffix of this language to name ApplicationResources.
To set the language used in the site, we use a servlet's filter to set the language used by the site, we can exist in the language used by the site, or exist in the session, and secure the user must use Chinese. Here we first fix the language used by the user is Chinese.
Establishing the STENCODEFILTER class First we create a new class name to setencodefilter:
The Filter interface will require the implementation class to implement the following methods:
Init: Initializing the work DOFILTER hours when Filter: Destroy Filter DoFilter: When there is a SERVET, the method of filtering, we don't write these three methods first, first configure this filter to the web application. Configuring a web application Using Filter First We open Web.xml, add Filter's declaration in the web-app content:
In order to use this filter, we also have to set the scope of the filter, add the following after the Filter declaration:
Implementation Language Content Filter The following is the code content:
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 imports filter {
/ ** * Configuration information of this filter * / protected filterconfig filterconfig = NULL;
/ ** * System default language code * / protected string defaultencoding = null;
/ ** * initialize filter * / public void init (FilterConfig filterConfig) throws ServletException {this.filterConfig = filterConfig; // Get the system default language code this.defaultencoding = filterConfig.getInitParameter ( "defaultencoding");}
/ * ** filtration system requests, coding language setting request * / public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {request.setCharacterEncoding (selectEncoding (request)); chain.doFilter (request, response }
/ ** * Filter destroy * / public void destroy () {this.defaultencoding = null; this.filterconfig = null;}
/ ** * Select the language code used by this filter * @Param Request This time servlet request user request instance * @return Select language code * / protected string selectencoding (servletRequest request) {// can join from here SESSION is obtained in the requestion and obtain the encode // selected by the user from the session can also join the eNCode from Request to get the encode (this.defaultencoding);}}.
The code will not explain one by one, and the comments inside are also very clear.
Join Hibernate Configuration SessionFactory's initialization Struts plugin Specific addition method This is no longer explained, please refer to the description of the Plugin to Struts in the Hibernate Development Guide, here is just listing code:
Package com.huangdong.dbwebdemo;
Import javax.naming.context; import javax.naming.initialcontext; import javax.naming.namingexception; import javax.servlet.servletException;
Import net.sf.hibelption; 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 {
/ ** * Plug-in container context instance * / private context ctx; / ** * Hibernate initializes good sessionFactory * / private meansionFactory sessionFactory;
/ * * Plug-in destruction method * / public void destroy () {if (ctx! = Null) {Try {// unbind jndi node ctx.unbind ("HibernateSessionFactory");} catch (namingexception e) {E.PrintStackTrace () }}} If (this.SessionFactory! = Null) {Try {// Close sessionFactory sessionFactory.Close ();} catch (hibernateException e) {E.PrintStackTrace ();} this.SessionFactory = null;}} / * * the method of plug-in initialization * / public void init (ActionServlet servlet, ModuleConfig config) throws ServletException {try {// Get an instance of SessionFactory this.sessionFactory = new Configuration () configure () buildSessionFactory ();..} catch (HibernateException ex) { throw new RuntimeException ( "Exception building SessionFactory:" ex.getMessage (), ex);} try {// container made context ctx = new InitialContext (); // sessionFactory bind to the JND tree ctx.bind ( "HibernateSessionFactory ", This.SessionFactory;} catch (namingexception ex) {throw new runtimeexception (" Exception Binding SessionFactory to JNDI: " EX.g EtMessage (), EX);}}
} The session gain tool class In addition to configuring the use of Plugin, we still use a class named DBUTIL class with the same function as HibernateUTilPlus, the following is its code:
Package com.huangdong.dbwebdemo;
Import javax.naming.context; import javax.naming.initialcontext; import javax.naming.namingexception;
Import net.sf.hibelnate.hibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory;
/ ** * @Author hd * / public class dbutil {
PRIVATETIC sessionFactory sessionFactory = NULL; public static final threadlocal session = new threadlocal ();
public static Session currentSession () throws HibernateException {if (sessionFactory == null) {// If sessionFactory instance is null if acquired from the JNDI (getSystemSessionFactory () == false) {throw new HibernateException ( "Exception geting SessionFactory from JNDI" );}} Session s = (session) session.get (); if (s == null) {s = sessionFactory.opensesis (); session.set (s);} returnis} public static void CloseSession () THROWS HibernateException {session s = (session) session.get (); session.set (null); if (s! = null) s.close ();} private static boolean getSystemSessionFactory () {Try {// From JNDI to obtain a SessionFactory, if an error return false Context inttex = new InitialContext (); sessionFactory = (SessionFactory) inttex.lookup ( "HibernateSessionFactory");} catch (NamingException e) {return false;} return true;}} Hibernate configuration Don't forget that we have to write Hibernate's configuration files (here you can see the environment preparations in the Hibernate Development Guide):
xml version = '1.0' encoding = 'UTF-8'?>
session-factory>
Hibernate-Configuration> Settings Data Table Subject Map The Oracle Database of We are still using a few articles. So the connection configuration is almost almost. Our increase, delete, change, and check or use the sysuser table, so use the original MAP file. The following is the source code for the SYSUser class:
Package com.huangdong.dbwebdemo.da;
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 imports 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 = usrname;}
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 return false ((other instanceof SysUser)!); SysUser castOther = (SysUser) other; return new EqualsBuilder () .append (this.getUserid (), castOther.getUserid ()) .isEquals ();
Public Int hashcode () {return new hashcodebuilder (). append (). tohashcode ();
} There is also a mapped XML file:
XML Version = "1.0" encoding = "UTF-8"?>
This way we have created a new Sysuserform class in a com.huangdong.dbwebdemo.form packet. Let's join the relevant properties and set geter and set, the following is the code:
Package com.huangdong.dbwebdemo.form;
Import org.apache.struts.action.validatorform;
Public class sysuserform extends validatorform {
/ / -------------------------------------------------------------------------------------------- --------- Instance variables / ** User ID, read-only * / private string userid;
/ ** User Name * / Private String UserName;
/ ** User Password * / Private string UserPasword;
/ ** Last login time * / private string lastlogin; public sysuserform () {super ();}
Public sysuserform (Sysuser sysuser) {this.newsysuserform (sysuser.getuserid (), sysuser.getuserPasword (), sysuser.getLastLoginstr ());}
Public sysuserform (String Userid, String User, String UserPasword, String LastLogin) {this.newsysuserform (userid, username, userpasword, lastlogin);} // -------------------------------------------------------------------------------------------- --------------------------------------METHODS / ** * is filled for a new Sysuserform data * / private void newSysuserForm (String userid, String username, String userpasword, String lastlogin) {this.userid = userid; this.username = username; this.userpasword = userpasword; this.lastlogin = lastlogin;} / ** * @ RETURN Last login time * / public string getLastLogin () {return LastLogin;}
/ ** * @return user ID * / public string getUserid () {return userid;}
/ ** * @return username * / public string getUsername () {return username;}
/ ** * @Return user password * / public string getUserPasword () {return UserPasword;}
/ ** * @Param String Last login time, format YYYY-MM-DD HH: mm: ss * / public void setlastlogin (string string) {LastLogin = String;}
/ ** * @Param String User Name * / Public Void SetUserName (String String) {username = string;}
/ ** * @param string User Password * / public void setUserpasword (String string) {userpasword = string;} / ** * of the form submission check * / public ActionErrors validate (ActionMapping mapping, HttpServletRequest request) {ActionErrors errors = Super.validate (mapping, request); return errors;
Here we see that our FORMBEAN has joined the functionality of the data check, and will be carefully described below. At the same time, in order to convert related constructors and private methods for transformations with Hibernate's database.
Establish the first Action to join the definition of Action in Struts-Config.xml, as follows:
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 .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 {
// Initialization System Language Resource Locale Locale = getLocale (Request); MessageResources message = getResources; // This action Default Receive request to create a new Sysuser string action = "create"; return (mapping.findforward) Action));}} The two sentences here are the local message resource file language code used to set the VIEW. The data of the relationship VO to the PO association VO to the PO is represented by the data of the traffic layer, and the PO is the data of the persistent layer. VO will use a lot of usage when viewing and business processing, that is, all data before entering the library will be stored in a VO. And Po is the persistent data structure of the database in Java.
Many people like to combine the Struts's VO with Hibernate's PO, I don't agree, there are many reasons, the most important thing is:
Vo has its own data properties, and due to the differences in the framework, there may be our own structure and method. I like to use FormBean in Struts, which is also a large number of business operations in a class Vo of the ACTIONForm. Such as verification, automatic generation, etc., the relationship between the dataset is included, such as the relationship in the database, also reflects one-to-one, more-to-many, one-on-one, etc. in the PO, but not necessarily in VO. Pay attention to this detail, I prefer to use one or more associated classes to map VO and PO in business logic, implement VO to PO conversion, and the removal of VO in PO.
The operation of all VO to PO and PO operations is basically deposited or changed (deleted) of the persistent layer data. Such an operation will definitely involve transaction operations of the database. On the other hand, the data of PO to VO involves the buffer, paging, and other techniques such as data sets. So we declare two abrasions for these two situations:
The AbsbaseMap class mainly completes data operations of VO to PO:
Package com.huangdong.dbwebdemo.db;
Import net.sf.hibelption; import net.sf.hibernate.Session; import net.sf.hibernate.transaction;
Import com.huangdong.dbwebdemo.dbutil;
/ ** * System VO and PO Operation Map Class, complete database transaction and connection initialization and database transaction submission and database connection close * @Author hd * / public abstract class absbasemap {// database connection session private SESSION session; // Database transaction processor Private Transaction Transaction;
/ * ** * initialize database connectivity transaction database connection initialization completion @return * @throws HibernateException * / public Session beginTransaction () throws HibernateException {session = DBUtil.currentSession (); transaction = session.beginTransaction (); return session;}
/ ** * Complete a database transaction * @Param commit is submitted to transaction, True Submit, False Time Database hair rollback (ROLLBACK) * @Throws HibernateException * / public void endTransaction (Boolean commit) throws HibernateException {if (commit) {Transaction.commit ();} else {transaction.rollback ();} DBUTIL.CLOSESSESSSION ();}} AbsqueryMap class is mainly provided with an abstract method for queries for persistent layer data: package com.huangdong.dbwebDemo.db ;
/ ** * System VO and PO's query mapping abstract class, add query paging related settings * @Author hd * / public class absquerymap {/ ** * Database connection session ** / session session;
// Page 20 INT Pagesize = 20; // Current page INT PAGENO = 1;
/ ** * @return page number size (default is 20) * / public int getpageSize () {return Pagesize;}
/ ** * @Param i sets the number of page numbers * / public void setpagesize (INT i) {pageSize = i;} / ** * @return Returns the current page number, the initial value is 1 * / public int getPageno () { Return Pageno;
/ ** * @Param i set the current page number * / public void setpageno (int i) {PAGENO = i;
/ ** * Setting query * / public void setQueryPage (query query) {// Set Pipement Start Record Number Query.setFirstResult ((this.pageno - 1) * this.pageSize); // Setting the page Data Queue Query .SETMAXRESULTS (this.pageSize);
/ ** * Open the current database connection * @Return * @Throws HibernateException * / public void initssis () THROWS HibernateException {this.Session = dbutil.currentSession ();}
/ ** * Close the current database connection * @throws hibernateException * / public void closesession () throws hibernateException {dbutil.closesession () after (), all our database update operations inherit the AbsbaseMap class, and the database query operation will inherit AbsqueryMap class.
Database increasing, deletion, and change Operation Map Once you have the features provided by the AbsbaSemap abstract class and Hibernate provided, we only need to know a little bit of Java's knowledge to complete complex database updates.
First, create a new class named SysuserMap in com.huangdong.dbwebdemo.db package and extend the ABSBaseMap class:
Package com.huangdong.dbwebdemo.db;
Import com.huangdong.dbwebdemo.form.sysuserform; public class sysusermap extends absbasemap {
} Firstly, an increased method, in the VO layer, the data class we use is SYSUSERFORM, so the parameter of the increase method must be SYSUSERFORM:
public void createSysUser (SysuserForm sysuerForm) throws HibernateException {// attributes related to the use of the new sysuser sysuerForm Examples SysUser sysuser = new SysUser (sysuerForm.getUsername (), sysuerForm.getUserpasword (), Calendar.getInstance ()); // start transaction Session Session = this.begintransaction (); try {// Add this instance into the database session.save (sysuser); // Commit this.endtransaction (true);} catch (hibernateException E) {// rollback this.endtransaction False); throw e;}} This method is very simple, and the writing is completely unreasonable.
Then we will write updated code, compared to the same simple:
/ * ** Update contains a sysuser * @param sysuerForm updated content sysuser form bean * @throws HibernateException * / public void updateSysUser (SysuserForm sysuerForm) throws HibernateException {// use the relevant attributes sysuerForm sysuser new instance SysUser sysuser = new SysUser ( Sysuerform.getuserName (), sysuerform.getuserPasword (), Calendar.GetInstance ()); // Start transaction session session = this.begintransaction (); try {// Add this instance into the database session.Update (sysuser); // Commit this.endTransaction (TRUE);} catch (hibernateException e) {// rollback this.endtransaction (false);}} Let's write a content more code - delete. Delete is generally deleted using the user ID, so the parameter can be a FORMBEAN with a user ID or a user ID, we use two ways to implement deletion:
Form Bean * @throws HibernateException / ** * based on a user to remove the sysuser formbean * @param sysuerForm containing the user information * / public void deleteSysUser (SysuserForm sysuerForm) throws HibernateException {String userid = sysuerForm.getUserid (); this. deleteSysUser (userid);} / ** * based on the user ID of the user to delete * @param userid user ID * @throws HibernateException * / public void deleteSysUser (String userid) throws HibernateException {Session session = this.beginTransaction (); try { // Query if there is this user sysuser sysuser = (sysuser.class, userid); // kill it! Session.delete (Sysuser); this.endTransaction (TRUE);} catch (hibernateException e) {this.endtransaction (false);}}} The database is relatively complex, we start from simplicity, do not use it first Any spare parts, query all records in the database. Create a sysuserqueMap class in com.huangdong.dbwebdemo.db, which extends AbsqueryMap Class: package com.huangdong.dbwebdemo.db;
Import java.util.iterator;
Import net.sf.hibelnate.hibernateException; import net.sf.hibernate.query;
/ ** * @Author hd * / public class sysuserQuerymap extends absqurymap {public sysuserQuerymap () throws hibernateException {this.initssession ();}
public Iterator findAllSysUser () throws HibernateException {// query String querystr = "from SysUser"; // Create a query Query query = this.session.createQuery (querystr); // set page this.setQueryPage (query); // returns The result set return query.iterate ();}} Here we have written a way to query all users, its first sentence:
String queryStr = "from sysuser"; here's query statement uses Hibernate's HQL syntax, other we don't need to manage, here Sysuser is case sensitive, we define the Sysuser database map class, here must be exactly the same, this Hibernate An instance of all Sysuser classes will be removed from the database.
Next, we also need a method to return to the user corresponding to the user's ID.
/ ** * * Examples of queries that a user UserID @return * @param user UserID example of a user UserID, if no corresponding record database returns 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;} With this method, we can specify The user is inquiry or modifies the information he has.
Creating the first View New JSP page We first set a JSP page for adding records, which provides a VIEW that adds records.
| | | | "userid" scope = "request"> logic: EMPTY> VIEW public check JavaScript code page below We list the contents of StaticJavaScript.jsp: <% @ Page language = "java"%> <% - set document type to javascript (addresses a bug in netscape agent (addresses a bug in netscape accounting to a web resource -%> <% @ Page ContentType = "Application / X-javascript"%> <% @ Taglib URI = "/ Web-INF / STRUTS-HTML.TLD" prefix = "html"%> Associating business logic to an Action adding This action will process all the operations associated with Sysuser, so the requests received by the Action will have multiple requests, and we add the following code in the Execute method: IF ("create")) {// If the processing request type is CREATE Request.setttribute ("sysuserform", new sysuserform ()); action = "create";} else if (action.equals ("add ")) {// If the processing request type is add sysusermap sysusermap = new sysusermap (); try {sysusermap.createsysuser (sysuser); // Join success, let us first add a user request.settribute (" sysuserform ", New sysuserform ()); action = "create";} catch (hibernateException e) {// Data stock = new actionerrors errors = new actionerrors (); errors.add (actionerrors.global_ERror, new actionerror ("error.database.save ", E.tostring ()); this.saveErRors (Request, Errors); // Display the current data back and display to re-enter Request.settribute (" sysuserform ";" sysuserform "; action =" create "; } This business operation is very simple, mainly calling MAP to store VO into PO, complete a function of adding a record to the database. Our specific implementation is to create a new FormBean to store the user's input, then place the data in the FORMBEAN into the database. If an error occurs while depositing, we turn the contents of this Exception into the error in the JSP (you can look back to see the content in the JSP). Next, we complete deletion, change, check, and these operations are also very simple. IF (action == null || action.equals ("list")) {// If the processing request type is list sysuserQuerymap sqm = new sysuserQueryMap (); iterator sysuserlist = sqm.findallsysuser (); request.settribute ("sysuserlist" , Sysuserlist); action = "list";} This code is defined when the following is the operation of all users when the List operation is requested. It is actually called the FindallSysuser in the previously completed SysuserQueryMap to remove all users from the database. The user list then pressed into the bean. if (action.equals ( "edit")) {// request type edit SysUserQueryMap sqm = new SysUserQueryMap (); String uid = request.getParameter ( "userid"); request.setAttribute ( "sysuserForm", sqm.getSysuserByID ( UID);} else if ("Update")) {// Request type is update sysusermap sysusermap = new sysusermap (); sysusermap.UpdateSysuser (sysuser); action = "list";} This code is completed Edit the work of user data. We can see that the first need to complete an Edit work, the role of this operation is to acquire this user information from the database, and then press this user information into the FORMBEAN to display. After the user changes the information, complete the UPDATE operation, update the database entry. IF ("delete")) {// If the processing request type is 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); } An action = "list";} This code completes the deleted function. Delete the specified entry. If an error is pressed, it is incorrect to a global error. Data input to forms is verified in Struts with a data check frame called Validator in Jakarta Commons. It is also very simple to use. First put the profile of the Validator-Rules.xml provided by Struts in web-infers. Then add the Validation of Validation in Struts-Config.xml: |