天天看點

【Struts2+Hibernate4】按照MVC思想使用Hibernate查詢資料庫,并且在前台使用OGNL表達式輸出

本文将介紹Struts2與Hibernate的整合,兩東西的整合并不需要用到Spring,完全可以各司其職,Struts2完成Java檔案與Jsp頁面互動,Hibernate完成資料庫到Java檔案的互動。

一、基本目标

還是那張在Mysql中已經用爛的Testtable表。

【Struts2+Hibernate4】按照MVC思想使用Hibernate查詢資料庫,并且在前台使用OGNL表達式輸出

在index.jsp點選查詢之後,能夠把這張表的所有内容輸出出來。而且表格是梅花間竹的不同顔色。當然這個例子已經很多書籍上說過了。

【Struts2+Hibernate4】按照MVC思想使用Hibernate查詢資料庫,并且在前台使用OGNL表達式輸出

目錄結構如下,嚴格按照MVC思想。

【Struts2+Hibernate4】按照MVC思想使用Hibernate查詢資料庫,并且在前台使用OGNL表達式輸出

二、基本準備

1、這裡就不再多說了,在Eclipse for Javaee建立一個Web工程之後,把Struts2必備的包,具體可以參考《【Struts2】Struts2純手工安裝、配置以及Helloworld,以最新版struts 2.3.20 GA做例子》(點選打開連結)與Hibernate必要的包,具體可以參考《【Hibernate】Hibernate的在Eclipse+Mysql的配置、安裝,純Java,利用Annotation與HQL完成資料庫的增删改查》(點選打開連結)放到WEB-INF檔案夾下的lib目錄。最後lib檔案夾如下圖:

【Struts2+Hibernate4】按照MVC思想使用Hibernate查詢資料庫,并且在前台使用OGNL表達式輸出

2、之後在web.xml隻需要配好Struts2就可以了,Hibernate是一個Java插件來的,有包就可以用了。無須配置,具體如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>
           

三、制作過程

1、首先先寫好持久層M吧。在src根目錄下的hibernate.cfg.xml與《【Hibernate】Hibernate的層次劃分,Hibernate4.3的初始化的新寫法》(點選打開連結)唯一的差別就是最後一行指明Test表的映射Java是test.model.TestTable.java。而不是根目錄下的TestTable.java:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<!--所用的資料庫驅動  -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<!--所用的資料庫登陸密碼  -->
		<property name="hibernate.connection.password">root</property>
		<!--所用的資料庫名稱為test,根據實際更改 -->
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
		<!--所用的資料庫使用者名  -->
		<property name="hibernate.connection.username">root</property>
		<!--所用的資料庫方言,與所用資料庫驅動一樣,可以在網上查到,這裡是mysql -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
		<property name="hibernate.format_sql">true</property>
		<!--如果是update表明Hibernate将保留原來的資料記錄,插入時把新記錄添加到已有的表,-->
		<!--如果是create,則總是建立新的表,如果原來資料庫已有的這個表,則這個表的記錄會被全部清洗  -->
		<property name="hibernate.hbm2ddl.auto">update</property>
		<!--羅列Testtable表與Java檔案的映射,這裡就Testtable.java的一張表,是以就寫一個Testtable.java  -->
		<mapping class="test.model.Testtable" />
	</session-factory>
</hibernate-configuration>
           

至于TestTable.java則一字未改,TestTable還是那個TestTable.java,隻是因為這裡是在Web工程的test.model包中,是以打頭多了一個包名。

package test.model;
import javax.persistence.*;

@Entity
@Table(name = "testtable")
public class Testtable {
	private int id;
	private String username;
	private String number;

	// 表示主鍵與自動生成項
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@Column(name = "username")
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	@Column(name = "number")
	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	@Override
	public String toString() {
		return id + "," + username + "," + number;
	}

}
           

2、同樣一直未改的還有資料庫服務類dbDAO.java,資料庫服務完全通過hql語句操作,以後要搞直接使用本類中的方法就可以了。再也不用管Hibernate中奇奇怪怪的執行事務的Session初始化問題,不用再也一堆語句,就為了初始化那個Session。

package test.model;

import org.hibernate.*;
import org.hibernate.cfg.*;
import org.hibernate.service.*;
import org.hibernate.boot.registry.*;

public class dbDAO {
	private Session session;

	// 構造函數,初始化Session,相當于連接配接資料庫
	public dbDAO() {
		//這裡使用了Hibernate4.3.8的寫法,這裡Hibernate又把初始化的方法修改了,非常蛋疼
		Configuration cfg = new Configuration().configure();
		ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
				.applySettings(cfg.getProperties()).build();
		SessionFactory sessionFactory = cfg
				.buildSessionFactory(serviceRegistry);
		this.session = sessionFactory.openSession();
	}
	
	// 執行查詢
	public Query query(String hql){
		return session.createQuery(hql);
	}
	
	// 執行插入、修改
	public void save(Object object){
		Transaction transaction=session.beginTransaction();  
		session.save(object);
		transaction.commit(); 
	}
	
	// 執行删除
	public void delete(Object object){
		Transaction transaction=session.beginTransaction(); 
		session.delete(object);
		transaction.commit(); 
	}

	// 析構函數,中斷Session,相當于中斷資料庫的連接配接
	protected void finalize() throws Exception {
		if (session.isConnected() || session != null) {
			session.close();
		}
	}

}
           

3、之後再來寫C層。首先在src建立并配置好Struts.xml,指明query這個Action的執行方法是test.action.query.java

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC  
      "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
      "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	<!-- 在test包裡面 -->
	<package name="test" extends="struts-default">
		<!-- action為query的執行方法就是test包中的action包query.java中的run方法 -->
		<action name="query" class="test.action.query" method="run">
			<result name="success">/index.jsp</result>
		</action>
	</package>
</struts> 
           

4、query.java是本WEB工程中C層的唯一Action類當然也是核心Action類。無須從起來要來任何資料。直接像《【Hibernate】Hibernate的層次劃分,Hibernate4.3的初始化的新寫法》( 點選打開連結)的HQL.java,Java與資料庫的互動一樣,引入test.model中整個包,裡面包含Testtable類與資料庫業務邏輯dbDAO.java,直接用HQL語句對Testtable類進行查詢取出整張Testtable表。并且把它壓入一個存放Testtable類的List動态數組testtableList裡面,用getter方法推向前台。當然setter方法完全可以不要,隻是利用Eclipse順帶生成而已。

package test.action;

import test.model.*;

import java.util.*;

//這是Struts2必要的支援
import com.opensymphony.xwork2.ActionSupport;

//防止報序列号警告
@SuppressWarnings("serial")
// Struts2必須繼承這個類
public class query extends ActionSupport {
	private List<Testtable> testtableList;

	//防止JDK1.5的泛型警告
	@SuppressWarnings("unchecked")
	public String run() {
		dbDAO db = new dbDAO();
		testtableList = db.query("from Testtable").list();
		return "success";
	}

	//eclipse自動生成
	public List<Testtable> getTesttableList() {
		return testtableList;
	}

	public void setTesttableList(List<Testtable> testtableList) {
		this.testtableList = testtableList;
	}

}
           

5、最後是V層,就一個index.jsp,運用到ognl表達式,注意在打頭引入s标簽,這東西與JSTL表達式也就是c标簽《【Servlet】利用Servlet3.0标準與JSTL表達式實作檔案上傳系統,支援圖檔上傳後顯示》( 點選打開連結)沒有差別,但注意在相當于<c:if>的<s:if>中不相容EL表達式《【Filter】利用過濾器Filter解決post傳遞的編碼問題與利用EL表達式簡化參數傳遞》( 點選打開連結),裡面隻能是<s:if>自己的東西,其它s标簽才可以。先是判斷testtableList是否有值,因為在使用者沒有點查詢超級連結的時候,根本不應該輸出testtableList這張表。之後利用到相當于<c:foreach>的<s:iterator>輸出整張表。輸出的過程中判斷是否是單行,如果是,則此列背景顔色是灰色。

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查詢</title>
</head>
<body>
	<a href="./query" target="_blank" rel="external nofollow" >查詢</a><br />
	<s:if test="testtableList">
		testTable表如下:
		<table >
			<s:iterator value="testtableList" id="testtable" status="st">
				<s:if test="#st.odd"><tr style="background-color: #cccccc"></s:if>
				<s:else><tr></s:else>
					<td>${testtable.id}</td>
					<td>${testtable.username}</td>
					<td>${testtable.number}</td>
				</tr>
			</s:iterator>
		</table>
	</s:if>
</body>
</html>
           

四、總結與展望

Struts2+Hibernate4整個開發流程中運用到的MVC思想其實與《【Servlet】根據MVC思想設計使用者登陸、使用者注冊、修改密碼系統》(點選打開連結)是一模一樣的,正如jQuery是JavaScript的架構一樣。Struts2+Hibernate4能做到的事情Jsp/JSTL+Servlet+JDBC也能夠做到。

繼續閱讀