好了,你填写了全部的输入域,提交了这个表单(没有任何验证错误),瞧:你又回到了相同的表单,全部的格子里面都是空的。发生了什么,数据都到哪儿去了?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,它提供了几乎是海量的教程哦。