(今天是2007年国庆日,能在今天加班搞农业普查数据处理,并抽闲翻译这样一篇seam文章,真的是特别特别有意义噢。
)
通过写带标注的普通java类,seam使创建应用变得非常容易。这样的类不需要扩展任何特殊的接口或超类。通过提供一系列内置组件,我们可以进一步简化一些通用的编程工作。对这些内置组件的使用是通过设置xomponents.xml(适用于简单情况)或其他的设置。
在一个应用中,如果需要使用Hibernate 或 JPA对数据库进行基本操作,Seam 应用程序框架可以减少编码数量。
需要强调的是,这个框架极其简单,仅仅少量的简单易懂的、易于扩展的类。“魔法”就在seam本身-即使你创建seam应用时没有使用这个框架,你也在使用同样的魔法。
11.1. 前言
Seam 应用程序框架提供的组件可以用以下两种方式之一使用:
第一种,在components.xml安装、设置组件实例,就像我们使用其他类型seam组件。例如,以下components.
xml代码片段安装一个组件,可以对Person entity进行基本操作:
<
framework:entity-home
name
="personHome"
entity-class
="eg.Person"
entity-manager
="#{personDatabase}"
>
<
framework:id
>
#{param.personId}
</
framework:id
>
</
framework:entity-home
>
如果这样看起来太像“在xml中编程”,亦可以这样使用扩展方式:
@Stateful
@Name(
"
personHome
"
)
public
class
PersonHome
extends
EntityHome
<
Person
>
implements
LocalPersonHome
{
@RequestParameter String personId;
@In EntityManager personDatabase;
public Object getId() { return personId; }
public EntityManager getEntityManager() { return personDatabase; }
}
第二种方式有较大优势:可以方便地加入额外函数,并覆盖内置函数(为便于扩展和定制,框架类已被仔细设计)。
第二个优势是,你的类可以是EJB stateful sessin beans(并非必须如此,只要你愿意,也可以是plain JavaBean components)。
截至目前,seam应用程序框架提供了四种内置组件:EntityHome 、HibernateEntityHome
for CRUD、EntityQuery 、 HibernateEntityQuery for queries。
Home 与 Query组件可以用在这些工作期中:session, event 或conversation。使用何种工作期取决于你的应用程序的状态模型。
seam应用程序框架仅适用Seam-managed persistence contexts。默认情况,组件将查找名称为entityManager的persistence context。
11.2. Home objects
一个Home object提供了对一个特定entity class的持久化操作(persistence operations)。假设有这样一个Person类:
@Entity
public
class
Person
{
@Id private Long id;
private String firstName;
private String lastName;
private Country nationality;
//getters and setters...
}
我们可以定义一个personHome 组件,以设置的方式:
<
framework:entity-home
name
="personHome"
entity-class
="eg.Person"
/>
或者以扩展的方式:
@Name(
"
personHome
"
)
public
class
PersonHome
extends
EntityHome
<
Person
>
{}
一个Home object提供了以下操作:persist(), remove(), update() and getInstance()。在调用remove(), 或 update()操作之前,必须首先用setId()设置对象的标志符。
可以在JSF页面中使用Home对象,例如:
<
h1
>
Create Person
</
h1
>
<
h:form
>
<
div
>
First name:
<
h:inputText
value
="#{personHome.instance.firstName}"
/></
div
>
<
div
>
Last name:
<
h:inputText
value
="#{personHome.instance.lastName}"
/></
div
>
<
div
>
<
h:commandButton
value
="Create Person"
action
="#{personHome.persist}"
/>
</
div
>
</
h:form
>
通常,如果在引用Person的时候,直接使用person就太好了,因此,我们通过在components.xml中加入一行来做到这点(如果我们使用设置的方式):
<
factory
name
="person"
value
="#{personHome.instance}"
/>
<
framework:entity-home
name
="personHome"
entity-class
="eg.Person"
/>
或者可以通过加入@Factory方式到PersonHome(如果我们使用扩展的方式):
@Name(
"
personHome
"
)
public
class
PersonHome
extends
EntityHome
<
Person
>
{
@Factory("person")
public Person initPerson() { return getInstance(); }
}
以上改变简化了JSF页面:
<
h1
>
Create Person
</
h1
>
<
h:form
>
<
div
>
First name:
<
h:inputText
value
="#{person.firstName}"
/></
div
>
<
div
>
Last name:
<
h:inputText
value
="#{person.lastName}"
/></
div
>
<
div
>
<
h:commandButton
value
="Create Person"
action
="#{personHome.persist}"
/>
</
div
>
</
h:form
>
好了,我们新建一个Person entries。是的,这就是所需的全部代码!现在,如果我们想要显示、更新、删除数据库中的Person 记录,则需要把记录的id传给PersonHome。做到这点,页参数是一个好办法:
<
pages
>
<
page
view-id
="/editPerson.jsp"
>
<
param
name
="personId"
value
="#{personHome.id}"
/>
</
page
>
</
pages
>
现在可以向JSF页面加入更多操作:
<
h1
>
<
h:outputText
rendered
="#{!personHome.managed}"
value
="Create Person"
/>
<
h:outputText
rendered
="#{personHome.managed}"
value
="Edit Person"
/>
</
h1
>
<
h:form
>
<
div
>
First name:
<
h:inputText
value
="#{person.firstName}"
/></
div
>
<
div
>
Last name:
<
h:inputText
value
="#{person.lastName}"
/></
div
>
<
div
>
<
h:commandButton
value
="Create Person"
action ="#{personHome.persist}"
rendered ="#{!personHome. persist }" />
<h:commandButton value=" Update Person"
action ="#{personHome.update}"
rendered ="#{personHome.managed}" />
<
h:commandButton
value
="Delete Person"
action ="#{personHome.remove}"
rendered ="#{personHome.managed}" />
</
div
>
</
h:form
>
如果到该页面的连接不带任何请求参数,会显示"Create Person"页面。
如果针对personId 提供一个请求参数,会显示"Edit Person"页面。假设我们需要建立一条Person记录,包含初始化的国籍信息。非常简单,通过设置的方式:
<
factory
name
="person"
value
="#{personHome.instance}"
/>
<
framework:entity-home
name
="personHome"
entity-class
="eg.Person"
new-instance
="#{newPerson}"
/>
<
component
name
="newPerson"
class
="eg.Person"
>
<
property
name
="nationality"
>
#{country}
</
property
>
</
component
>
或者通过扩展的方式:
@Name(
"
personHome
"
)
public
class
PersonHome
extends
EntityHome
<
Person
>
{
@In Country country;
@Factory("person")
public Person initPerson() { return getInstance(); }
protected Person createInstance() {
return new Person(country);
}
}
The Seam Application Framework
当然,Country 可能是一个由其他Home object管理的对象,例如,CountryHome。为了增加更多复杂操作(例如关联管理,等等),我们可以对PersonHome增加方法(methods)。
@Name(
"
personHome
"
)
public
class
PersonHome
extends
EntityHome
<
Person
>
{
@In Country country;
@Factory("person")
public Person initPerson() { return getInstance(); }
protected Person createInstance() {
return new Person(country);
}
public void migrate()
{
getInstance().setCountry(country);
update();
}
}
如果一个操作成功完成,Home对象自动显示faces messages。为定制这些信息,我们再一次通过设置的方式:
<
factory
name
="person"
value
="#{personHome.instance}"
/>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
framework:entity-home
name
="personHome"
entity-class
="eg.Person"
new-instance
="#{newPerson}"
>
<
framework:created-message
>
New person #{person.firstName} #{person.lastName} created
</ framework:created-message >
<
framework:deleted-message
>
Person #{person.firstName} #{person.lastName} deleted
</ framework:deleted-message >
<
framework:updated-message
>
Person #{person.firstName} #{person.lastName} updated
</ framework:updated-message >
</
framework:entity-home
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
component
name
="newPerson"
class
="eg.Person"
>
<
property
name
="nationality"
>
#{country}
</
property
>
</
component
>
或者使用扩展的方式:
@Name(
"
personHome
"
)
public
class
PersonHome
extends
EntityHome
<
Person
>
{
@In Country country;
@Factory("person")
public Person initPerson() { return getInstance(); }
protected Person createInstance() {
return new Person(country);
}
protected String getCreatedMessage()
{
return "New person #{person.firstName} #{person.lastName} created";
}
protected String getUpdatedMessage()
{
return "Person #{person.firstName} #{person.lastName} updated";
}
protected String getDeletedMessage()
{
return "Person #{person.firstName} #{person.lastName} deleted";
}
}
不过定制信息的最好方式是把它们放到一个seam找得到的资源包中(这个包的默认名称是 messages)。
Person_created=New person #{person.firstName} #{person.lastName} created
Person_deleted=Person #{person.firstName} #{person.lastName} deleted
Person_updated=Person #{person.firstName} #{person.lastName} updated
11.3. Query objects
如果需要数据库中 Person 记录列表,可以用Query 对象,例如:
<
framework:entity-query
name
="people"
ejbql
="select p from Person p"
/>
可以在JSF页面这样用它:
<
h1
>
List of people
</
h1
>
<
h:dataTable
value
="#{people.resultList}"
var
="person"
>
<
h:column
>
<
s:link
view
="/editPerson.jsp"
value
="#{person.firstName} #{person.lastName}"
>
<
f:param
name
="personId"
value
="#{person.id}"
/>
</
s:link
>
</
h:column
>
</
h:dataTable
>
如果需要分页:
<
framework:entity-query
name
="people"
ejbql
="select p from Person p"
order
="lastName"
max-results
="20"
/>
我们需要也各页面参数来确定显示哪一页:
<
pages
>
<
page
view-id
="/searchPerson.jsp"
>
<
param
name
="firstResult"
value
="#{people.firstResult}"
/>
</
page
>
</
pages
>
JSF分页控制代码有点繁琐,但是比较易于控制:
<
h1
>
Search for people
</
h1
>
<
h:dataTable
value
="#{people.resultList}"
var
="person"
>
<
h:column
>
<
s:link
view
="/editPerson.jsp"
value
="#{person.firstName} #{person.lastName}"
>
<
f:param
name
="personId"
value
="#{person.id}"
/>
</
s:link
>
</
h:column
>
</
h:dataTable
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
s:link
view
="/search.xhtml"
rendered
="#{people.previousExists}"
value
="First Page"
>
<
f:param
name
="firstResult"
value
="0"
/>
</
s:link
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
s:link
view
="/search.xhtml"
rendered
="#{people.previousExists}"
value
="Previous Page"
>
<
f:param
name
="firstResult"
value
="#{people.previousFirstResult}"
/>
</
s:link
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
s:link
view
="/search.xhtml"
rendered
="#{people.nextExists}"
value
="Next Page"
>
<
f:param
name
="firstResult"
value
="#{people.nextFirstResult}"
/>
</
s:link
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
s:link
view
="/search.xhtml"
rendered
="#{people.nextExists}"
value
="Last Page"
>
<
f:param
name
="firstResult"
value
="#{people.lastFirstResult}"
/>
</
s:link
>
真正的搜索页面允许使用者输入一系列选择性的搜索条件,缩小返回的搜索结果数目。
Query对象允许你指定可选的“限制条件”来支持这种重要功能。
<
component
name
="examplePerson"
class
="Person"
/>
<
framework:entity-query
name
="people"
ejbql
="select p from Person p"
order
="lastName"
max-results
="20"
>
<
framework:restrictions
>
<
value
>
lower(firstName) like lower( concat(#{examplePerson.firstName},'%') )
</
value
>
<
value
>
lower(lastName) like lower( concat(#{examplePerson.lastName},'%') )
</
value
>
</
framework:restrictions
>
</
framework:entity-query
>
注意一个"example" 对象的使用。
<
h1
>
Search for people
</
h1
>
<
h:form
>
<
div
>
First name:
<
h:inputText
value
="#{examplePerson.firstName}"
/></
div
>
<
div
>
Last name:
<
h:inputText
value
="#{examplePerson.lastName}"
/></
div
>
<
div
><
h:commandButton
value
="Search"
action
="/search.jsp"
/></
div
>
</
h:form
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
h:dataTable
value
="#{people.resultList}"
var
="person"
>
<
h:column
>
<
s:link
view
="/editPerson.jsp"
value
="#{person.firstName} #{person.lastName}"
>
<
f:param
name
="personId"
value
="#{person.id}"
/>
</
s:link
>
</
h:column
>
</
h:dataTable
>
后台记录改变后,为刷新查询结果,我们观察
org.jboss.seam.afterTransactionSuccess 事件:
<
event
type
="org.jboss.seam.afterTransactionSuccess"
>
<
action
execute
="#{people.refresh}"
/>
</
event
>
或者,当person记录通过 PersonHome保存、更新、删除后,为马上刷新查询:
<
event
type
="org.jboss.seam.afterTransactionSuccess.Person"
>
<
action
execute
="#{people.refresh}"
/>
</
event
>
以上例子显示了通过设置的方式达到复用。不过,对Query 对象来说,通过扩展的方式达到复用也是同样可以的。
11.4. Controller objects
在Seam应用框架中完全可选的部分是Controller 类和它的子类Entity-Controller HibernateEntityController 和 BusinessProcessController。它们提供了操作常用的内置组件及其方式的捷径。它们可以节省击键次数(自动添加字符),对新手学习seam的内在功能有很大的推动作用。
例如,Seam registration例子中的RegisterAction看上去像这样:
@Stateless
@Name(
"
register
"
)
public
class
RegisterAction
extends
EntityController
implements
Register
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
@In private User user;
public String register()
{
List existing = createQuery("select u.username from User u where u.username=:username")
.setParameter("username", user.getUsername())
.getResultList();
if ( existing.size()==0 )
{
persist(user);
info("Registered new user #{user.username}");
return "/registered.jspx";
}
else
{
addFacesMessage("User #{user.username} already exists");
return null;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
如你所见,应用它们后并没有带来明显的改善... ...
以上是翻译 Seam Reference Documentation 2.0.0 CR1第十一章的内容。
欢迎赐教。
![](/Editor/FCKeditor/editor/images/smiley/msn/regular_smile.gif)
通过写带标注的普通java类,seam使创建应用变得非常容易。这样的类不需要扩展任何特殊的接口或超类。通过提供一系列内置组件,我们可以进一步简化一些通用的编程工作。对这些内置组件的使用是通过设置xomponents.xml(适用于简单情况)或其他的设置。
在一个应用中,如果需要使用Hibernate 或 JPA对数据库进行基本操作,Seam 应用程序框架可以减少编码数量。
需要强调的是,这个框架极其简单,仅仅少量的简单易懂的、易于扩展的类。“魔法”就在seam本身-即使你创建seam应用时没有使用这个框架,你也在使用同样的魔法。
11.1. 前言
Seam 应用程序框架提供的组件可以用以下两种方式之一使用:
第一种,在components.xml安装、设置组件实例,就像我们使用其他类型seam组件。例如,以下components.
xml代码片段安装一个组件,可以对Person entity进行基本操作:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
如果这样看起来太像“在xml中编程”,亦可以这样使用扩展方式:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
第二种方式有较大优势:可以方便地加入额外函数,并覆盖内置函数(为便于扩展和定制,框架类已被仔细设计)。
第二个优势是,你的类可以是EJB stateful sessin beans(并非必须如此,只要你愿意,也可以是plain JavaBean components)。
截至目前,seam应用程序框架提供了四种内置组件:EntityHome 、HibernateEntityHome
for CRUD、EntityQuery 、 HibernateEntityQuery for queries。
Home 与 Query组件可以用在这些工作期中:session, event 或conversation。使用何种工作期取决于你的应用程序的状态模型。
seam应用程序框架仅适用Seam-managed persistence contexts。默认情况,组件将查找名称为entityManager的persistence context。
11.2. Home objects
一个Home object提供了对一个特定entity class的持久化操作(persistence operations)。假设有这样一个Person类:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
我们可以定义一个personHome 组件,以设置的方式:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
或者以扩展的方式:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
一个Home object提供了以下操作:persist(), remove(), update() and getInstance()。在调用remove(), 或 update()操作之前,必须首先用setId()设置对象的标志符。
可以在JSF页面中使用Home对象,例如:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
通常,如果在引用Person的时候,直接使用person就太好了,因此,我们通过在components.xml中加入一行来做到这点(如果我们使用设置的方式):
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
或者可以通过加入@Factory方式到PersonHome(如果我们使用扩展的方式):
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
以上改变简化了JSF页面:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
好了,我们新建一个Person entries。是的,这就是所需的全部代码!现在,如果我们想要显示、更新、删除数据库中的Person 记录,则需要把记录的id传给PersonHome。做到这点,页参数是一个好办法:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
现在可以向JSF页面加入更多操作:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
action ="#{personHome.persist}"
rendered ="#{!personHome. persist }" />
<h:commandButton value=" Update Person"
action ="#{personHome.update}"
rendered ="#{personHome.managed}" />
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
action ="#{personHome.remove}"
rendered ="#{personHome.managed}" />
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
如果到该页面的连接不带任何请求参数,会显示"Create Person"页面。
如果针对personId 提供一个请求参数,会显示"Edit Person"页面。假设我们需要建立一条Person记录,包含初始化的国籍信息。非常简单,通过设置的方式:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
或者通过扩展的方式:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
当然,Country 可能是一个由其他Home object管理的对象,例如,CountryHome。为了增加更多复杂操作(例如关联管理,等等),我们可以对PersonHome增加方法(methods)。
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
如果一个操作成功完成,Home对象自动显示faces messages。为定制这些信息,我们再一次通过设置的方式:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
New person #{person.firstName} #{person.lastName} created
</ framework:created-message >
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
Person #{person.firstName} #{person.lastName} deleted
</ framework:deleted-message >
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
Person #{person.firstName} #{person.lastName} updated
</ framework:updated-message >
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
或者使用扩展的方式:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
{
return "New person #{person.firstName} #{person.lastName} created";
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
{
return "Person #{person.firstName} #{person.lastName} updated";
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
{
return "Person #{person.firstName} #{person.lastName} deleted";
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
不过定制信息的最好方式是把它们放到一个seam找得到的资源包中(这个包的默认名称是 messages)。
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
这使国际化成为可能,并且使你的代码和设置与表现信息分离。
11.3. Query objects
如果需要数据库中 Person 记录列表,可以用Query 对象,例如:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
可以在JSF页面这样用它:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
如果需要分页:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
我们需要也各页面参数来确定显示哪一页:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
JSF分页控制代码有点繁琐,但是比较易于控制:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
真正的搜索页面允许使用者输入一系列选择性的搜索条件,缩小返回的搜索结果数目。
Query对象允许你指定可选的“限制条件”来支持这种重要功能。
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
注意一个"example" 对象的使用。
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
后台记录改变后,为刷新查询结果,我们观察
org.jboss.seam.afterTransactionSuccess 事件:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
或者,当person记录通过 PersonHome保存、更新、删除后,为马上刷新查询:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
以上例子显示了通过设置的方式达到复用。不过,对Query 对象来说,通过扩展的方式达到复用也是同样可以的。
11.4. Controller objects
在Seam应用框架中完全可选的部分是Controller 类和它的子类Entity-Controller HibernateEntityController 和 BusinessProcessController。它们提供了操作常用的内置组件及其方式的捷径。它们可以节省击键次数(自动添加字符),对新手学习seam的内在功能有很大的推动作用。
例如,Seam registration例子中的RegisterAction看上去像这样:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
如你所见,应用它们后并没有带来明显的改善... ...
以上是翻译 Seam Reference Documentation 2.0.0 CR1第十一章的内容。
欢迎赐教。