您的位置:首页 > 其它

Hibernate3官方教程-第1章-第3部分

2008-01-11 22:54 253 查看
1.4.第3部分-EventManager web application
一个Hibernate也像一个独立的应用那样使用会话和事务,然而,一些常见的模式是有用的,我们现在写一个EventManagerServlet,这个Servlet可列出数据库中所有的events,并且提供一个表单用以增加新的event。

1.4.1.编写基本的Servlet
在源代码目录新建一个Servlet,隶属events包:

package events;

// Imports

public class EventManagerServlet extends HttpServlet {

// Servlet code
}

此Servlet仅仅处理Get请求,因此我们将要实现的方法是doGet():

protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");

try {
// Begin unit of work
HibernateUtil.getSessionFactory()
.getCurrentSession().beginTransaction();

// Process request and render page...

// End unit of work
HibernateUtil.getSessionFactory()
.getCurrentSession().getTransaction().commit();

} catch (Exception ex) {
HibernateUtil.getSessionFactory()
.getCurrentSession().getTransaction().rollback();
throw new ServletException(ex);
}

}

这里我们应用的模式叫做:每个请求一个会话(session-per-request)。当一个请求抵达Servlet的时候,通过首次对SessionFactory上的getCurrentSession()的调用,打开一个新的Hibernate会话,然后一个数据库事务就开始了——所有的数据访问都在这一个事务中进行,不管是读还是写(在实际应用中我们不使用自动提交的模式)。

不要为每个数据库操作都创建一个新的Hibernate会话,在一个请求范围内使用一个会话,使用getCurrentSession()会自动的将会话绑定到当前Java线程。

接下来,请求可能的动作处理并且输出渲染(render)好的HTML数据,我们稍后讨论这块。
最后,处理和渲染(render)完毕工作就结束了,如果在处理中有任何错误发生,一个异常就会被抛出,事务就会回滚。session-per-request模式就完成了。与其在每个Servlet中编写事务分割代码,不如写一个Servlet Filter(过滤器),关于这个模式,可以查阅Hibernate的网站和Wiki站点,叫做在视图中打开会话(Open Session in View)——如果你打算通过JSP处理视图而不是Servlet,你就需要阅读下它。

1.4.2.处理和渲染
我们来实现请求处理代码以及页面渲染的代码:

// Write HTML header
PrintWriter out = response.getWriter();
out.println("<html><head><title>Event Manager</title></head><body>");

// Handle actions
if ( "store".equals(request.getParameter("action")) ) {

String eventTitle = request.getParameter("eventTitle");
String eventDate = request.getParameter("eventDate");

if ( "".equals(eventTitle) || "".equals(eventDate) ) {
out.println("<b><i>Please enter event title and date.</i></b>");
} else {
createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate));
out.println("<b><i>Added event.</i></b>");
}
}

// Print page
printEventForm(out);
listEvents(out, dateFormatter);

// Write HTML footer
out.println("</body></html>");
out.flush();
out.close();

必需承认,这是一个混合了Java代码和HTML的代码风格,它在一个更复杂的应用中将变得不够灵活——请注意,在本教程我们仅仅举例介绍Hibernate的基本概念,并且仅仅需要输出HTML而已:

private void printEventForm(PrintWriter out) {
out.println("<h2>Add new event:</h2>");
out.println("<form>");
out.println("Title: <input name='eventTitle' length='50'/><br/>");
out.println("Date (e.g. 24.12.2009): <input name='eventDate' length='10'/><br/>");
out.println("<input type='submit' name='action' value='store'/>");
out.println("</form>");
}

listEvents()方法绑定到当前Java线程的Hibernate会话去执行一个查询:

private void listEvents(PrintWriter out, SimpleDateFormat dateFormatter) {

List result = HibernateUtil.getSessionFactory()
.getCurrentSession().createCriteria(Event.class).list();
if (result.size() > 0) {
out.println("<h2>Events in database:</h2>");
out.println("<table border='1'>");
out.println("<tr>");
out.println("<th>Event title</th>");
out.println("<th>Event date</th>");
out.println("</tr>");
for (Iterator it = result.iterator(); it.hasNext();) {
Event event = (Event) it.next();
out.println("<tr>");
out.println("<td>" + event.getTitle() + "</td>");
out.println("<td>" + dateFormatter.format(event.getDate()) + "</td>");
out.println("</tr>");
}
out.println("</table>");
}
}

最后,store动作被发送到createAndStoreEvent()方法,该方法使用的也是当前线程的会话:

protected void createAndStoreEvent(String title, Date theDate) {
Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDate(theDate);

HibernateUtil.getSessionFactory()
.getCurrentSession().save(theEvent);
}

现在,Servlet就写完了,一个向Servlet的请求会被一个单独的会话和事务处理。像以前的独立应用那样,Hibernate也可以自动的将对象绑定到当前执行线程,这给了你充分的自由去做代码分层,并以任何你喜欢的方式访问SessionFactory。通常,你最好使用一个更好的设计,把数据访问的代码放进数据访问对象(DAO模式)中,可以看Hibernate wiki来获得更多的示例。

1.4.3.部署并测试
为了部署这个应用,我们需要创建一个Web档案,一个WAR包,将以下内容加入你的Ant脚本:

<target name="war" depends="compile">
<war destfile="hibernate-tutorial.war" webxml="web.xml">
<lib dir="${librarydir}">
<exclude name="jsdk*.jar"/>
</lib>

<classes dir="${targetdir}"/>
</war>
</target>

这个target在工程目录创建了一个hibernate-tutorial.jar文件,它将依赖的类库以及web.xml都打包了在内。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>Event Manager</servlet-name>
<servlet-class>events.EventManagerServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Event Manager</servlet-name>
<url-pattern>/eventmanager</url-pattern>
</servlet-mapping>
</web-app>

在你编译并部署该Web应用以前,注意另外一个库是需要的:jsdk.jar,这是Java Servlet开发包,如果你还没有这个文件,从Sun网站下载并放在lib目录,然而它只在编译期间会使用到,在打war包的时候要排除在外。
执行ant war命令来编译并部署,将生成的hibernate-tutorial.jar文件复制到tomcat的webapp目录,如果你还没安装tomcat,下载并根据说明进行安装,不用做任何设置即可进行使用。
部署以后,启动tomcat,并通过以下地址访问:http://localhost:8080/hibernate-tutorial/eventmanager,当首个请求抵达servlet以后(HibernateUtil静态初始化方法被调用),注意查看tomcat的日志观察Hibernate初始化情况,并在出错的时候查看详细的日志输出。
1.5.总结
本教程涵盖了编写一个基本的独立应用程序,以及一个小型web应用的基础知识。
如果你对Hibernate学习建立起了自信,继续通过本参考文档内容目录查看你感兴趣的内容、主题——经常被问及的是事务处理(Chapter 11, Transactions And Concurrency),查询性能(fetch performance)(Chapter 19, Improving performance),或者API的用法(Chapter 10, Working with objects)),以及关于查询特性(Section 10.4, “Querying”)。
最后,别忘记多检查Hibernate网站以得到专门的教程。

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
英文原文版权归原作者所有, 本译文转载请注明出处!
译者:abigfrog 联系:QQ:800736, MSN:J2EE@HOTMAIL.COM

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: