今天这个例子主要是为了学习Hibernate,之前已经对Struts有了了解,因此加上Struts的控制,另外稍微加上了一点点Spring&Struts的使用。
使用工具:eclipse for J2EE,Tomcat6.0,JDK1.6,SQLServer2000。
此例子重点在于使用Hibernate的对数据库表的增删改查功能,以及分页的实现。
使用数据库:Pubs,复制其中的表titles为newtitles以供使用,复制表的代码为:
use pubs
select * into newtitles from titles;
alter table newtitles add primary key(title_id);
首先建立工程取名SSH2_Example(当然工程名任意起),然后环境配置,将所有要用到的jar包复制进工程lib里,关于jar包的引用就不多说了,这是个大问题,也是个应该没啥问题的问题,so...
工程下新建包,com.hp.db,这个包里我们放HibernateSessionFactory这个类,也是Hibernate的关键类,其功能就是提供数据库的连接,是个Session,相当于JDBC里的Connection,还可以提供事务的共通代码,代码如下:
package com.hp.db; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class HibernateSessionFactory { /** Hibernate的配置文件的位置 **/ private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml"; /** 设置本地线程变量,使多线程开发时保证线程的安全,Session和Transaction **/ private static final ThreadLocal
可以看到,HibernateSessionFactory类还需要一个Hibernate的配置文件,来共通完成对数据库的连接,配置文件名:hibernate.cfg.xml,放在src目录下,内容如下:
hibernate.cfg.xml中我们使用了连接池的技术,也需要个配置文件,文件名:proxool.xml,也同样放到src目录下,代码如下:
在hibernate.cfg.xml中我们看到有个Java类到数据库表的映射文件,
package com.hp.voo; import java.util.Date; /** * 同表名的映射类 * 数据类型都选用了对象类型,而没有使用基本数据类型,原因是属性和字段对应,只有对象才能 * 表示空值的概念,即数据库中的NULL。 * 另外,该对象实现了java.io.Serializable接口,表示这个对象能够进行串行化操作,例如保 * 存到硬盘、数据库或网络传输。 * */ public class Newtitles implements java.io.Serializable { private String titleId; private String title; private String type; private String pubId; private Double price; private Double advance; private Integer royalty; private Integer ytdSales; private String notes; private Date pubdate; /** Default constructor */ public Newtitles() { } /** Minimal constructor */ public Newtitles(String titleId, String title, String type, Date pubdate) { this.titleId = titleId; this.title = title; this.type = type; this.pubdate = pubdate; } /** Full constructor */ public Newtitles(String titleId, String title, String type, String pubId, Double price, Double advance, Integer royalty, Integer ytdSales, String notes, Date pubdate) { this.titleId = titleId; this.title = title; this.type = type; this.pubId = pubId; this.price = price; this.advance = advance; this.royalty = royalty; this.ytdSales = ytdSales; this.notes = notes; this.pubdate = pubdate; } public String getTitleId() { return titleId; } public void setTitleId(String titleId) { this.titleId = titleId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getPubId() { return pubId; } public void setPubId(String pubId) { this.pubId = pubId; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public Double getAdvance() { return advance; } public void setAdvance(Double advance) { this.advance = advance; } public Integer getRoyalty() { return royalty; } public void setRoyalty(Integer royalty) { this.royalty = royalty; } public Integer getYtdSales() { return ytdSales; } public void setYtdSales(Integer ytdSales) { this.ytdSales = ytdSales; } public String getNotes() { return notes; } public void setNotes(String notes) { this.notes = notes; } public Date getPubdate() { return pubdate; } public void setPubdate(Date pubdate) { this.pubdate = pubdate; } }
Newtitles.hbm.xml也放在com.hp.voo包中,代码如下:
同时,com.hp.voo包中,我们需要放入一个分页显示的POJO类,类中属性为分页所需的各种属性,譬如当前页码,总记录数,当前页的数据等等,类名:PageBean,代码如下:
package com.hp.voo; import java.util.ArrayList; import java.util.List; public class PageBean { private int allcount; //总记录数 private int allpage; //总页数 private int pagecode; //页码 private int pagesize; //每页记录数 private List data = new ArrayList(); //当前页数据 public int getAllcount() { return allcount; } public void setAllcount(int allcount) { this.allcount = allcount; } public int getAllpage() { return allcount % pagesize == 0 ? allcount / pagesize : allcount / pagesize + 1; } public List getData() { return data; } public void setData(List data) { this.data = data; } public int getPagecode() { return pagecode; } public void setPagecode(int pagecode) { this.pagecode = pagecode; } public int getPagesize() { return pagesize; } public void setPagesize(int pagesize) { this.pagesize = pagesize; } }
然后新建包,com.hp.base,这个包中将存放所有增删改查以及分页的基础方法,通过用泛型的方式,使其成为任何业务Bean都可以使用的通用增删改查的基础类,为了实现面向接口编程,我们这个包里放入一个接口,和一个实现类,接口名:IGenericDao,代码如下:
package com.hp.base; import java.io.Serializable; import java.util.List; import com.hp.voo.PageBean; /** * DAO=Data Access Object(数据访问对象) DAO模式接口,定义DAO的CRUD操作的抽象方法,用泛型实现通用的DAO实现 * */ public interface IGenericDao
实现类类名:GenericHibernateDao,代码如下:
package com.hp.base; import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.Criterion; import com.hp.db.HibernateSessionFactory; import com.hp.voo.PageBean; /** * DAO=Data Access Object(数据访问对象) DAO模式方法,定义DAO的CRUD操作的实现方法,用泛型实现通用的DAO实现 * */ public class GenericHibernateDao
下面再建个包,com.hp.dao,此包为业务类包,即我们要做的所有业务,同样用接口和实现类的方式来写,同时要继承刚才com.hp.base包中的基础接口和类,dao包下接口名为ITitlesDao,代码如下:
package com.hp.dao; import java.util.List; import com.hp.voo.Newtitles; import com.hp.voo.PageBean; /** * 定义业务用到的DAO方法接口,继承了基础CRUD的业务接口 * */ public interface ITitlesDao extends com.hp.base.IGenericDao
实现类的类名为TitlesDaoImp,代码如下:
package com.hp.dao; import com.hp.base.GenericHibernateDao; import com.hp.voo.Newtitles; import com.hp.voo.PageBean; /** * 定义业务用到的DAO方法,继承了基础CRUD的业务方法 * */ public class TitlesDaoImp extends GenericHibernateDao
接下来新建包,com.hp.actions,我们在这里放入我们的业务action,类名CrudAction,代码如下:
package com.hp.actions; import com.hp.dao.ITitlesDao; import com.hp.dao.TitlesDaoImp; import com.hp.voo.Newtitles; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; @SuppressWarnings("serial") public class CrudAction extends ActionSupport implements ModelDriven
继续新建个包,com.hp.filters,此包下放入所有的过滤器,我们主要是为了让页面提交时事务能自动提交然后关闭Session,所以使用它,过滤器名:SessionFilter2,代码如下:
package com.hp.filters; 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; import javax.servlet.http.HttpServlet; import com.hp.db.HibernateSessionFactory; public class SessionFilter2 extends HttpServlet implements Filter { public SessionFilter2() { // TODO Auto-generated constructor stub } public void destroy() { // TODO Auto-generated method stub } public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { try { arg2.doFilter(arg0, arg1); HibernateSessionFactory.commitTransaction(); } catch (Exception e) { HibernateSessionFactory.rollbackTransaction(); } finally { HibernateSessionFactory.closeSession(); } } public void init(FilterConfig fConfig) throws ServletException { // TODO Auto-generated method stub } }
src下的包都建完了,最后一项需要写struts.xml文件,目录也是src下,代码如下:
注意,里面多了一句使用Spring实例Action的命令,而且class="crudBySpring"一句如果不用Spring的话,需要写的是Action的路径,现在使用了Spring的话,只需要定义个名字跟Spring里的配置文件里的某个名字相同,会自动去找到Spring里同名的属性里的Action的路径,我们看到Spring的作用其实就是截了一下Action的创建的过程。
下面是spring的配置文件,文件名:applicationContext.xml,目录在WEB-INF下,代码如下:
最后就差页面和web.xml文件了,代码如下:
index.jsp:
<%@ page language="java" contentType="text/html; charset=windows-31j" pageEncoding="windows-31j"%>
TitlesList.jsp:
<%@ page language="java" contentType="text/html; charset=windows-31j" pageEncoding="windows-31j"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
Book ID | Book NM | Type | Price | Date | Do something |
${title.titleId} | ${title.title} | ${title.type} | ${p} | ${d} | Delete Update |
AddTitles.jsp:
<%@ page language="java" contentType="text/html; charset=windows-31j" pageEncoding="windows-31j"%> <%@ taglib uri="/struts-tags" prefix="s" %>
web.xml:
搞定收工。。。