好了,你填寫了全部的輸入域,提交了這個表單(沒有任何驗證錯誤),瞧:你又回到了相同的表單,全部的格子裏面都是空的。發生了什麼,數據都到哪兒去了?html
所發生的就是咱們尚未告訴Tapestry在表單成功提交(得是成功的,咱們的意思是,沒有驗證錯誤)以後接下來要作什麼。Tapestry的默認行爲是從新顯示當前的page,而這是在一個新的請求當中,Address對象已是一個新的實體了(由於address屬性域不是一個持久化的屬性域)。java
好吧,由於咱們已經建立了對象,咱們可能也應該將它們在某個地方存儲起來……在一個數據庫中。咱們準備將Hibernate快速集成到Tapestry中,做爲其對象/關係映射層,而且最終把數據存儲到一個HyperSQL(HSQLDB)數據庫中。HSQLDB是一個嵌入式的數據庫引擎,無需安裝——它將會由Maven做爲依賴獲取下來。web
咱們將吧這個項目從一個簡單的Tapestry項目慢慢變成一個使用了Hibernate和HSQLDB的Tapestry項目。sql
首先,咱們必須更新POM文件,添加一些新的依賴,包括Hibernate,Tapestry/Hibernate集成庫,以及HSQLDB JDBC驅動:數據庫
src/pom.xml(局部)apache
<dependencies>api
<dependency>服務器
<groupId>org.apache.tapestry</groupId>session
<artifactId>tapestry-hibernate</artifactId>app
<version>${tapestry-release-version}</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.2</version>
</dependency>
...
</dependencies>
Tapestry-hibernate庫包括Hibernate和tapestry-core。這意味着你能夠在<artifact>元素中簡單地將「tapestry-core」用「tapestry-hibernate」替換。
修改了POM並保存以後,Maven應該會自動下載新的依賴的JAR包。
Hibernate須要一個主配置文件,hibernate.cfg.xml,用來存儲鏈接和其它數據。在你的src/mian/resources 文件夾下面建立它:
src/main/resources/hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.url">jdbc:hsqldb:./target/work/t5_tutorial1;shutdown=true</property>
<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
</session-factory>
</hibernate-configuration>
配置的大部份內容用來指定JDBC驅動和鏈接的URL。
注意下鏈接的URL。咱們指示HSQLDB將其數據庫文件存儲在了項目的目標目錄。還指示HSQLDB在停掉應用時將數據刷到這些文件中。這意味着數據在項目的不一樣時期都會持續存在,但若是目標目錄被摧毀了(例如,經過「mvn clean」),那麼全部的數據庫內容都會丟失掉。
此外,咱們還配置了要Hibernate來更新數據庫的schema:當Hibernate初始化時它將會建立甚至於更新數據表,以匹配Java代碼中的實體類。最後,咱們配置Hibernate輸出其執行的任何SQL,這在一開始構建應用程序時很是有用。
然而有哪些實體呢?通常,可用的實體都會列在hibernate.cfg.xml中,不過使用Tapestry的話這就沒什麼必要了;在其它約定大於配置的示例中,Tapestry會定位全部位於entities包(這裏就是「com.example.tutorial1.entities」)中的實體類,並將它們添加到配置中。當前,就只有一個Address實體。
對於要用上Hibernate的實體,必須向其類中添加一些Hibernate的註解。
下面是更新事後的Address類,帶上了Hibernate的註解(還有就是Tapestry的)。
src/main/java/com/example/tutorial/entities/Address.java
package com.example.tutorial1.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.apache.tapestry5.beaneditor.NonVisual;
import org.apache.tapestry5.beaneditor.Validate;
import com.example.tutorial1.data.Honorific;
public class Address
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NonVisual
public Long id;
public Honorific honorific;
@Validate("required")
public String firstName;
@Validate("required")
public String lastName;
public String street1;
public String street2;
@Validate("required")
public String city;
@Validate("required")
public String state;
@Validate("required,regexp")
public String zip;
public String email;
public String phone;
}
Tapestry的註解,@NonVisual和@Validate,可能會被放置在setter或者getter或者屬性域之上(像咱們這裏這樣作的)。因爲使用了Hibernate的註解,將註解放置到了屬性域之上就要求屬性域的名稱對應到屬性的名稱。
l @NonVisual——表示一個屬性域,好比主鍵,應該不被用戶看見。
l @Validate——將驗證同屬性域關聯。
此處你應該中止並重啓應用程序。
這樣咱們就有了一個數據庫,而且Hibernate也被配置好了來鏈接它。讓咱們利用其來存儲咱們的Address對象。咱們所須要的是提供一些代碼在表單被提交時執行。當Tapestry的表單被提交時,有一系列的時間被觸發。咱們感興趣的是「success」事件,其在過程當中處在比較晚的後期,要等到全部的值都已經從請求中獲取到而且設置到page屬性上以後,還得是在全部服務器端驗證發生以後。
Success事件只會在沒有驗證錯誤的時候被觸發。
咱們的事件處理器必需要作兩件事:
l 使用Hibernate Session對象將新的Address對象持久化
l 將事務提交,強制讓數據被寫入數據庫。
讓咱們來更新一下CreateAddress.java類:
src/main/java/com/example/tutorial/pages/address/CreateAddress.java
package com.example.tutorial1.pages.address;
import com.example.tutorial1.entities.Address;
import com.example.tutorial1.pages.Index;
import org.apache.tapestry5.annotations.InjectPage;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.hibernate.annotations.CommitAfter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.hibernate.Session;
public class CreateAddress
{
@Property
private Address address;
@Inject
private Session session;
@InjectPage
private Index index;
@CommitAfter
Object onSuccess()
{
session.persist(address);
return index;
}
}
Inject註解會告訴Tapestry要將一個服務注入到註解的屬性域中;Tapestry包含一個複雜精緻的控制反轉容器(不少方面都相似於Spring),很是善於根據類型定位可用的服務,而不是根據string的id。不管什麼時候,Hibernate Session對象都是做爲一個Tapestry的IoC服務被暴露出來的,能夠被注入(這是一個由tapestry-hibernate模塊提供的東西)。
必要時Tapestry會自動開啓一個事務;不過該事務默認會在最後被取消。若是咱們隊持久化對象作了修改,好比添加了一個新的Address對象,那麼有必要提交這個事務。
CommitAfter註解能夠被應用於任何component的方法;若是方法照常完成,那事務就會被提交(並且一個新的事務會開始替換已經提交的事務)。
將新的地址持久化了以後,咱們要返回應用程序的Index page。
注意:在真實的應用程序中,不多會讓page和component直接使用Hibernate Sessin。通常更好的方式是定義你本身的數據訪問對象(Data Access Object)層來執行通用的更新和查詢操做。
做爲接下來的一個小預覽,下面所展現的是應用程序的Index page上由用戶輸入的全部地址數據。在你輸入了一些名字以後,看起來就會像下面這樣:
好吧,這是如何實現的呢?一般,這是由Grid componet實現的。
Grid component基於跟BeanEditForm component一樣的概念;它能夠將一個bean解析成數據列。數據列是能夠排序的,而且當數據量超過了一頁所能展現的量,分頁導航就會自動被加上。
最輕量的Grid很是容易被添加到模板中。只要把這個添加到Index.tml的底部就好了:
src/main/webapp/Index.tml (partial)
<t:grid source="addresses"
include="honorific,firstName,lastName,street1,city,state,zip,phone"/>
注意Grid component能夠接收咱們曾在BeanEditForm上使用過的相同的參數。這裏咱們使用include參數來指定要展現的屬性,還有使用哪一種順序。
現再咱們所要作的就是在Java代碼中提供這個addresses屬性。這裏展現了Index.java如今應該是什麼樣子:
src/main/java/com/example/tutorial/pages/Index.java
package com.example.tutorial1.pages;
import java.util.List;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.hibernate.Session;
import com.example.tutorial1.entities.Address;
public class Index
{
@Inject
private Session session;
public List<Address> getAddresses()
{
return session.createCriteria(Address.class).list();
}
}
這裏,咱們使用的是Hibernate Session對象找到數據庫中全部的Address對象數據。全部的排序都會在內存中完成。這在目前看來還好(只有幾個Address對象在數據庫中而已)。稍後咱們將會看到如何針對極大的結果集進行優化。
咱們還有更多要聊的:更多的component、更多的自定義、內置的Ajax支持,更多通用的設計和實現模式,甚至還要編寫你本身的組件(這很簡單!)。
去查看文檔頁面上衆多的Tapestry資源吧,包括入門和FAQ頁面,還有Cookbook。請確保要利用好用戶指南,它提供了幾乎每個Tapestry主題的很是詳細的信息。最後,確保看過(而且收藏了)Tapestry JumpStart,它提供了幾乎是海量的教程哦。