好了,你填写了所有的输入域,提交了这个表单(没有任何验证错误),瞧:你又回到了相同的表单,所有的格子里面都是空的。发生了什么,数据都到哪儿去了?

所发生的就是我们还没有告诉Tapestry在表单成功提交(得是成功的,我们的意思是,没有验证错误)之后接下来要做什么。Tapestry的默认行为是重新显示当前的page,而这是在一个新的请求当中,Address对象已经是一个新的实体了(因为address属性域不是一个持久化的属性域)。

好吧,因为我们已经创建了对象,我们可能也应该将它们在某个地方存储起来……在一个数据库中。我们准备将Hibernate快速集成到Tapestry中,作为其对象/关系映射层,并且最终把数据存储到一个HyperSQL(HSQLDB)数据库中。HSQLDB是一个嵌入式的数据库引擎,无需安装——它将会由Maven作为依赖获取下来。

重新对项目进行配置

我们将吧这个项目从一个简单的Tapestry项目慢慢变成一个使用了Hibernate和HSQLDB的Tapestry项目。

更新依赖

首先,我们必须更新POM文件,添加一些新的依赖,包括Hibernate,Tapestry/Hibernate集成库,以及HSQLDB JDBC驱动:

src/pom.xml(局部)

org.apache.tapestry

tapestry-hibernate

${tapestry-release-version}

org.hsqldb

hsqldb

2.3.2

...

Tapestry-hibernate库包括Hibernate和tapestry-core。这意味着你可以在元素中简单地将“tapestry-core”用“tapestry-hibernate”替换。

修改了POM并保存之后,Maven应该会自动下载新的依赖的JAR包。

Hibernate 配置

Hibernate需要一个主配置文件,hibernate.cfg.xml,用来存储连接和其它数据。在你的src/mian/resources文件夹下面创建它:

src/main/resources/hibernate.cfg.xml

hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

org.hsqldb.jdbcDriver

jdbc:hsqldb:./target/work/t5_tutorial1;shutdown=true

org.hibernate.dialect.HSQLDialect

sa

update

true

true

配置的大部分内容用来指定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的实体,必须向其类中添加一些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上由用户输入的所有地址数据。在你输入了一些名字之后,看起来就会像下面这样:

向Index page中添加一个表格

好吧,这是如何实现的呢?通常,这是由Gridcomponet实现的。

Grid component基于跟BeanEditForm component同样的概念;它可以将一个bean解析成数据列。数据列是可以排序的,并且当数据量超过了一页所能展示的量,分页导航就会自动被加上。

最轻量的Grid非常容易被添加到模板中。只要把这个添加到Index.tml的底部就行了:

src/main/webapp/Index.tml (partial)

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

 getAddresses()

{

return session.createCriteria(Address.class).list();

}

}

这里,我们使用的是Hibernate Session对象找到数据库中所有的Address对象数据。所有的排序都会在内存中完成。这在目前看来还好(只有几个Address对象在数据库中而已)。稍后我们将会看到如何针对极大的结果集进行优化。

接下来是什么?

我们还有更多要聊的:更多的component、更多的自定义、内置的Ajax支持,更多通用的设计和实现模式,甚至还要编写你自己的组件(这很简单!)。

去查看文档页面上众多的Tapestry资源吧,包括入门和FAQ页面,还有Cookbook。请确保要利用好用户指南,它提供了几乎每一个Tapestry主题的非常详细的信息。最后,确保看过(并且收藏了)Tapestry JumpStart,它提供了几乎是海量的教程哦。

h'tml和java代码,Tapestry 教程(七)在Tapestry中一起使用Hibernate相关推荐

  1. java代码转置sql数据_SQL Server中的数据科学:数据分析和转换–使用SQL透视和转置

    java代码转置sql数据 In data science, understanding and preparing data is critical, such as the use of the ...

  2. java 代码智能提示,如何在Eclipse中设置Java、JavaScript、HTML智能代码提示

    使用eclipse自带的插件,无需另外安装插件,具体步骤如下 1.打开eclipse→Windows→Preferences→Java→Editor→Content Assist 修改Auto Act ...

  3. java代码执行了两次_Java中JComboBox的itemStateChanged事件执行两次的解释

    今天做项目,用到了JComboBox,即下拉列表框.为了在被选中的项发生改变时获得被选中的项,所以使用的ItemStateChanged事件,可是问题就来了,每次触发该事件,它都执行两次,屡试不爽.一 ...

  4. 撩妹java代码_Java程序媛深入浅出设计模式中的撩妹神技--中篇

    开篇前言 遇一人白首,择一城终老,是多么美好的人生境界,她和他历经风雨慢慢变老,回首走过的点点滴滴,依然清楚的记得当初爱情萌芽的模样,时维十一月,眼看着光棍节就那么轻轻的来了,没有预告,没有准备`(* ...

  5. java代码安全检测机制,下列选项中,属于Java语言的代码安全检测机制的一项是______。A.动态链接B.访问权限的检查C.通过接...

    下列选项中,属于Java语言的代码安全检测机制的一项是______.A.动态链接B.访问权限的检查C.通过接 更多相关问题 Schema类型定义中当需要基于内置的基本数据类型定义一个新的数据类型时,用 ...

  6. Java代码怎么取消订阅功能,RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )...

    Github 相关代码: Github地址 一直感觉 RxJava2 的取消订阅有点混乱, 这样也能取消, 那样也能取消, 没能系统起来的感觉就像掉进了盘丝洞, 迷乱... 下面说说这几种情况 几种取 ...

  7. 撩妹java代码_Java程序媛深入浅出设计模式中的撩妹神技--下篇

    开篇前言 遇一人白首,择一城终老,是多么美好的人生境界,她和他历经风雨慢慢变老,回首走过的点点滴滴,依然清楚的记得当初爱情萌芽的模样,时维十一月,眼看着光棍节就那么轻轻的来了,没有预告,没有准备`(* ...

  8. java代码输出伞_在伞中集成测试Web应用程序的问题

    我正在研究凤凰应用程序 . 此应用程序是伞形应用程序的一部分 . 在这个保护伞中,我有一些小应用程序负责应用程序的不同区域,它们是: phoenix web api("api") ...

  9. Java CSS3:(七)CSS3 中常用的样式(跳动的心)

    CSS3 中常用的样式-跳动的心 做一个跳动的心 做一个跳动的心 <!DOCTYPE html> <html><head><meta charset=&quo ...

最新文章

  1. PCL :K-d tree 2 结构理解
  2. 第一课.图与图神经网络
  3. [20150113]关于oracle的存储结构.txt
  4. 《流浪地球》是一部违反科学常识的大烂片
  5. sklearn(聚类和降维)
  6. python分句_Python循环中的分句,继续和其他子句
  7. java 字符串匹配_多模字符串匹配算法原理及Java实现代码
  8. ubuntu12.04 安装 php5.4/php5.5
  9. 树形结构 —— 并查集
  10. CSS性能优化:可以试一试内联CSS?
  11. MVC教程第七篇:闲话ASP.NET
  12. HDU 2643 Rank:第二类Stirling数
  13. shell写入文件,后面会覆盖前面
  14. Android中最常用也是最难用的控件——ListView
  15. 全面屏手机有什么缺点?
  16. python可以下载百度文库_百度文档,用Python一键免费下载
  17. Flutter 画笔绘制二维码扫描框
  18. Excel十个让你事半功倍的函数
  19. 大数据面试之hive重点(二)
  20. 隐马尔科夫模型 HMM 与 语音识别 speech recognition (1):名词解释

热门文章

  1. 数字图像处理matlab上机实验 (八)
  2. 百度被黑后,中国黑客对伊朗网站展开全面反扑
  3. fatal error LNK1112: 模块计算机类型“X86”与目标计算机类型“x64”冲突——我的解决方案
  4. 大型B2C网站如何做好EDM营销
  5. linux 打印4 6照片,linux_2.6.30.4_Makefile_1--显示打印信息
  6. n阶差分方程重根计算公式的一般证明
  7. Android 9/10 Launcher3 适配出现的问题修改
  8. 淘宝自然搜索机制排名原理介绍,如何做好店铺商品自然搜索排名?
  9. 阅读感悟《给中年程序员的温暖人心的巴比奇的故事》
  10. pandownload下载完成却找不到所下载的文件 解决方法