??xml version="1.0" encoding="utf-8" standalone="yes"?>
Html 模板代码Q?
<h1> PopopLinklgQ?</h1><p>
作用Q弹Z个自定义的窗口,相当于一?Script语名Q?
<br> window.open(URL, windowName, windowFeatures) <br>
1.必须在Bodylg内用?<br>
2.注意href参数它会产生一个地址?context/href参数值?
<p> <span jwcid = "@contrib:PopupLink" href = "/WEB-INF/Home.html" features = 'ognl:"resizable,scrollbars,top=100,left=100,height=400,width=300"' > PopupLinkC?</span>
二?GenericLinkLink lg
Html 模板代码Q?
1.GenericLinkQ一般作用是用来链接跌{到应用程序范围以外的链接。注意OGNL用法Q?<br>
<a jwcid = "@GenericLink" href = "ognl:'http://'+url" >
<span jwcid = "@Image" image = "ognl:assets.ms" /> 163主页 </a><p>
url参数Q?
private String url="http://www.tkk7.com/happydavy/";
ms参数Q?
<context-asset name="ms" path="http://MS.JPG"/>
作用Q点d׃?163面?
三?.ExternalLink lg
Html 模板代码Q?
<span jwcid = "@ExternalLink" page = "LinkResult" parameters = 'ognl:new java.lang.Object[]{new java.lang.Integer("5"),new java.lang.String("rjzjh")}' >
ExternalLink使用 </span><p>
ExternalLink Q这lg?GenericLink lg复杂Q?Tapestry ?9 U?Service ?“external service?Q它的用法关?LinkResult c?
链接传递参?parameters Q多个参数用逗号隔开。链接的面 “LinkResult?必须实现 IExternalPage 接口Q必重?activateExternalPage Ҏ(gu)
在这个方法中我们可以把传递过来的参数取出来实现我们的逻辑。参数因为单引号内有双引P所以不能用双引P也可以调回来用了Q链接页的地址为: http://localhost:8080/context/app?service=external/LinkResult&sp=5&sp=Srjzjh
接收参数的页面要Q?
? 实现 IexternalPage 接口?
? 覆盖 public void activateExternalPage(Object[] parameters, IRequestCycle cycle) Ҏ(gu)?
如下 Java 文g为:
public void activateExternalPage(Object[] parameters, IRequestCycle cycle) {
this.setPar1((Integer)parameters[0]);
if(parameters.length==2){
this.setPar2((String)parameters[1]);
}
}
三?DirectLink lg
Html 模板为:
<p><span jwcid = "@DirectLink" listener = "ognl:listeners.directlistener" parameters = 'ognl:new java.lang.Object[]{new java.lang.Integer("8"),new java.lang.String("zjh")}' >
q是一个DirectLink链接
</span><br>
<span jwcid = "@DirectLink" listener = "ognl:listeners.DirectResult" parameters = 'ognl:new java.lang.Object[]{new java.lang.Integer("8"),new java.lang.String("zjh")}' >
W二个DirectLinkQ蟩转到LinkResult面
</span>
<br> DirectLink要传的参数是Q?
<span jwcid = "@Insert" value = "ognl:Directpar1" /> ?<span jwcid = "@Insert" value = "ognl:Directpar2" /><p>
W一个组件接收参数方法(监听事gQ:
public void directlistener(IRequestCycle cycle){
Object[] par=cycle.getServiceParameters();
this.setDirectpar1((Integer)par[0]);
this.setDirectpar2((String)par[1]);
}
W二个组件接收参数方法(在蟩转的面中写监听事gQ:
1 Q先跌{到另一个页面:
public void DirectResult(IRequestCycle cycle){
IPage result=cycle.getPage("LinkResult");
cycle.activate(result);
}
2 Q这时参C会随 Session 传到 LinkResult 面Q在 LinkResult 面中写监听事g?
public void getpar(IRequestCycle cycle) {
Object[] par=cycle.getServiceParameters();
this.setDirectpar2((String)par[1]);
this.setDirectpar1((Integer)par[0]);
}
你只需要构造这listrnerҎ(gu)Q而不是整个servlet。Tapestry会在正确的时候和正确的条件下调用listener的方法。你不需要考虑如何构造URLQ以及通过URL传递什么数据,或者如何结合到你的应用E序中去。这些工作框枉替你做好了?/P>
面和组?/P>
Tapestry把一个应用程序分成一pd的页面。每一个页面由Tapestry的组件组成。组件本w也许是q件构成。这里没有h为的深度?BR>tapestry面本n是lgQ只是有些特D用处的lg?BR>所有的tapestry的组件可以成为其他组件的容器。Tapestry面Q和许多用户定义的组件一P有一个模板,׃个特D的html定义了一些静态的和动态的lg位置Q同时有标签表明那些内嵌的组件是z跃的。组件不需要有标签。Tapestrylg参数也许是双向的Q一个组件可以读取一个参数来获得一个|或者写一个参数来讄一个倹{?/P>
其他的组件。如form和form控制lgQTextField, PropertySelection, Checkbox{等Q得html中的form的实现变得容易。当q样的组件被昄的时候,他们从程序对象中d属性值来提供默认倹{当form被提交的时候,form中的lgdhttp的查询参敎ͼ转换数gؓ合适的cdq且更新E序对象的属性?/P>
引擎Q服务和
随着旉的过去,Tapestry已经发展了它自己的方a?BR>Tapestry的引擎是一个一对象Z心的Q它的作用和Httpsession在Servlet API的作用?引擎的最l职责是存储应用E序的持久状态(从一个请求到下一个请求时存在的属性)Q这个Q务已l通过把引擎存贮在httpsession的方式被完成了。本文档主要讨论默认的实现Q同时标注如何在适当的时候扩展,重写q些实现?/P>
对Tapestry的高度评h"对象Q方法和属?Q也是_不仅仅开发者关注Servlet的APIQrequests, responses, sessions, attributes, parameters, URLs{等QTapestry使得开发者更x于对象(包括Tapestry的页面和lgQ而且包括E序的对象)Q对象的Ҏ(gu)以及那些对象的javaBean的属性。也是_在一个tapestry的程序中Q用L动作Q点击链接,提交表单Q会D对象的属性的变化Q这些属性和用户支持的方法(包括E序逻辑Q组合在一赗?/P>
在Tapestry中,你不需要写servletQ你只要写一些ListenerҎ(gu)Q你同样不需要ؓservlet建立URLQ你可以利用一个存在的lgQ例如DirectLinkQƈ配置他的listener的参数来调用Ҏ(gu)。那么Listener的方法到底做了什么呢Q它和后台系l进行交互(通常是无状态的session EJBQ或者是做一些其他的和request相关的记录,同时提供l用户一个新的页面。基本上是这个servlet的核心代码。在tapestry中,你不需要写那些重复的,机械的代码(例如建立urlQ分发请求,理服务器段的状态等{)Q因为那些都被tapestryq个框架完成了?/P>
但是qƈ不表CServlet API是不可访问的Q它仅仅是不跟一个典型的tapestry用户相关?/P>
本文档描qC很多tapestry的一些内在的情况。本文不是教E(教程是另外一个单独的文档Q。事实上Q本文档是给一些tapestry的用L指南Q目的是l那些想使用tapestry的开发者?/P>
tapestry目前的版本是 4.0Q在q去的十几年里已l过了长的发展。Tapestry始终x于生成动态的html代码Q尽有大量的Y件支持XHTML XML ?WML?/P>
几乎所有的Tapestry的API都是一接口的Ş式出玎ͼ同时有默认的实现。只要用新的对象取代现有的接口,框架的行为可以被很容易的取代。最q_的例子就是重载一个存贮的面和它的组Ӟ也许存贮在数据库中)?/P>
最后,Tapestry有值得自豪的完整的JavaDoc的文档。本文档是用来支持那份文档的Q来填补那分文档的一些不明显的不뀂当然JavaDoc是最好的文档?/P>
也许理解Tapestry最隄部分是它是一个以Zlg的,而不是以Z操作的。大多数的技术(StrutsQservlets, PHP{等Q都是基于操作的。当你徏立一个servlet以后Q当用户点击一个链接或者提交一个form的时候机会调用它。你必须选定一个适当的链接,和要传递参数的名字和类型,q样你才能在URL中传递你所需要的信息?/P>
对于那些操作Q点击链接或提交表单Q,你同样必负责去q接你的外部面Q不他们是JSPQservlets, PHP,或者其他Ş式的模板技术)。这需要你建立URLq且把他们放C?lt;a>的标{中Q或者是攑֜一?lt;form>标签的action属性中?/P>
tapestry中所有的东西都是不同的。TapestryE序由页面组成,面是由的lg构成Q组件本w也有可能由其他lg构成。每一个页面都׃个唯一的名字,面中的每个lg都有它唯一的ID...q就是组件模型。同Ӟ每一个组仉有一个地址Q可以快速的和URLq行l定?/P>
事实上,在“向购物车添加物品”的操作中,你不需要写servletQ甚至也不用写组件。你只需要拿一个已有的lgQ例如(DirectLinkQ?然后配置它。当q个lg被显C的时候,它会建立一个回调的链接Q当你点击这个链接的时候,q个回调链接Q包括了面名称和页面内的组件的IDQ将会调用组件上的方法,然后q个Ҏ(gu)׃调用你的E序制定的ListenerҎ(gu)
Tapestry是一个用Java语言~写的开源框Ӟ用于创徏动态的、健壮的、高灉|性的web应用E序。Tapestry框架构筑在标准的Java Servlet API之上Q因此它能够很好地兼容Q何servlet容器或者应用服务?/P>
Tapestry一个web应用E序分离Zl页面,而每个页面又由多个组件组成。这提供了一个协调一致的l构Q得Tapestry框架能够专注于Q何一个关键细节,例如QURL解析和派遣、持久化状态储存在客户端还是储存在服务器端、用戯入效验、本地化或国际化、和异常报告。对 Tapestry应用E序的开发包括:使用普通的HTML标签创徏HTML模板Q然后用XML描述文gQ可选)这些模板与量的java代码l合在一赗在Tapestry中,创徏你的应用E序是通过使用对象、方法以及对象的属性-Q-而ƈ非由URLs和查询参数。Tapestry带来了真正的 Java Web应用E序OOP~程?/P>
Tapestry能够非常Ҏ(gu)地创建新lgQ就如同以常规的步骤来构建应用程序一栗而官Ҏ(gu)供了过五十U组Ӟq些lg包括各种各样单的输出lgQ以及非常复杂的表格lg和树型目录组件?/P>
Tapestry能够构徏Q从型的应用程序到各种大型团队开发的几百个独立页面的大型应用E序。Tapestry能够非常Ҏ(gu)C各种底层框架l合Q包括J2EE、Hivemind和Spring?/P>
Tapestry发布于Apache Software Licence 2.0?/P>
Tapestry׃下四U关键原则组成:
q四U原则共同组成了一个宗旨:最单的选择Q就是最正确的选择。越早选择Tapestry框架Q那么就早避免许多ȝ?/P>
我们发现面向lg式web开发是实现q些原则的最好途径。围l着lg来组l框架和你的应用E序Q让框架来替你实现那些o人厌烦的底层代码。你只需要写量的代码,写一些简单的代码Q有时候你甚至不需要写代码。Tapestry让你L?/P>
Tapestry4.0增加了许多新Ҏ(gu)以便提高你的工作效率:
可以列D出无数Tapestry 4.0的变化。MQ所有的变化都是令h震撼的,减少了开发者的java代码Q减了模板的复杂性,化(或者除去)了XML文g?/P>
Tapestry 4.0的开发工作仍在全力进行中。文档从以前旧的DocBook形式转变到新的Forrest形式Q剔除了许多临时性间隔。指南中新的Quick Start章节已经被撰写?/P>
Tapestry 4.0已经接近最l的beta周期Q新Ҏ(gu)将会被延箋到Tapestry 4.1Qƈ会l逐步完善文档和修正bug。最l版本的Tapestry 4.0预计Q不保证Q会?005q十月推出?/P>
作ؓTAPESTRY-620修正的一部分Q将当前的IRquestCycle作ؓ可注入的serviceQ简化Tapestry中的一些接口,取消IRequestCycle参数。这可能要求对一些地方的代码实现作适当调整?/P>
在beta-10和之后的版本中,对于asset serviceQfriendly URLs的配|改变了。在你的hivemind.xml中,?lt;asset-encoder id="asset" path="/assets/"/> 改ؓ<asset-encoder id="asset" path="/assets"/>Q注意斜杠已l被LQ?/P>
Tapestry 4.0h很多新特性,考虑到向后兼Ҏ(gu),有些地方做了限制。具体细节以后会发布Q但是至:
升的时候,你将遇到下列问题Q?/P>
2 数据库中有以下数?BR> ID(pri)(Auto) name pass
1 aaa 111
2 bbb 222
3 ccc 333
L一条SQL语句现有的三条记录复制一下,辑ֈ以下的效?BR> ID(pri) (Auto) name pass
1 aaa 111
2 bbb 222
3 ccc 333
4 aaa 111
5 bbb 222
6 ccc 333
再用一条sql删除重复记录
q个要hotman_xq个sqlA来回{了Q呵?/P>
3 在服务器端,从一个jsp面中蟩到另外一个jsp面中有几种Ҏ(gu)Q?/P>
4 数据库中表结构如下,
IDQPriQ?nbsp; int
no int
name varchar
birthDay Date
用java写一个函?q回所有符合条?no = int a & name = str $ birthdavy = date 的结果集?/P>
5 jsp和Servlet的区别和联系
6 设计一个权限管理模型,分ؓaQb两组 al的一般用户只能读取a的tableQal中的管理员可以对a的tableq行CRUD
同样Qbl的一般用户只能读取b的tableQbl中的管理员可以对b的tableq行CRUD
理员可以对aQb的tableq行CRUD
写出部分实现代码
7 居然q有一家公司让我用30分钟的时间作?0道脑{急{弯,我得?6分,呵呵
上面的题目除了那个sql的题目我没做出来Q别的题目还是让公司比较满意?呵呵
HelloTalker ht=(HelloTalker)context.getBean(“helloTalker?;
System.out.println(ht.greeting());
}catch(Exception e)
{
e.printStackTrace();
}
}
}
q个E序完成了Q因为只有一个对象HelloTalker被注册到了spring中,所以不存在对象间的依赖Q当然也׃涉及依赖注入。下面演CZ个简单的依赖注入Q?BR> W一步是修改HelloTalkerQ增加一个String name属性:
public String name;
属性编写setҎ(gu)Q该Ҏ(gu)必须严格遵守javabean的命名规则:
public void setName(String name)
{
this.name=name;
}
修改greetingҎ(gu)Q?/P>
public String greeting()
{
return "hello "+name;
}
如你所见,name属性没有初试化Q因为它的值将在运行过E中被spring动态注入?BR> W二步,修改springConfig.xml中唯一的这个bean配置Q?/P>
<bean id=”helloTalker?class=?org.bromon.spring.test.HelloTalker?gt;
<property name=”name?gt;
<value>bromon</value>
</property>
</bean>
修改完成。我们将一个名字”bromon”写dspringConfig.xml中,它会被动态的注入到HelloTalker的name属性中QgreetingҎ(gu)会把它打印出来。重新运行刚才的junitc,可以看到l果?BR> 我们只演CZ如何注入一个最单的StringQ实际上我们可以注入M值类型,也可以注入Q何类的实例,也可以注入List、Map、Properties。配|文件管理了所有的对象和对象间的关p,而对象则只负责执行自q功能Q他们的职责少Q藕合度低Q系l就容易测试,理l护也更Ҏ(gu)?BR> <bean>标签q有很多属性,用于指定对象如何被实例化Q它也有很多子标{于配|对象的属性,请大家参考相关的DTD和文档,能够很快的掌握。本pd文章不是spring手册Qspring的基知识请参考spring in actionQ够详l准。后面的章节更多的讨论系l设计、开发的一些细节和高Ҏ(gu)?BR>三、spring中的hibernate开?
spring中对hibernate的支持是非常强大的,从一个简单的例子q得出来,从这个例子中我们q将Ҏ(gu)谓的轻量U容器做一些讨论?BR> 首先需要配|数据源Q通常我们有两U方式获得ConnectionQ一是自q写代码获得连接,二是从JNDI环境中得到DataSourceQ然后生一个Connection。无论怎样Q既然是spring下面的对象,应该注册到配置文g中。假设我们需要一个连接mysql下面一个叫做examer的数据库Q手动方式的配置是:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/examer</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value></value>
</property>
</bean>
很好L不是Q假如我们用JNDI数据源,那么dataSource的声明就应该是:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:compenvjdbcspringExamer</value>
</property>
</bean>
你需要在JNDI环境中绑定一个名为jdbc/springExamer的东西,q段代码才有实际意义。另外需要提醒的是,所有的bean声明Q它的id必须是唯一的?BR> 在本pȝ中,数据库操作是被hibernate装h的,所以dataSource是不需要注入到具体的逻辑cMQ它只会被注lhibernate的sessionFactory?BR> 按照常规思\Q我们需要在spring中注册hibernate的sessionFactoryQ它应该是我们自q写的一个类Q获得dataSourceQ返回sessionFactoryQ其他的逻辑c通过q个sessionFactory获得sessionq行数据库操作?BR> 但是我们有另外一U选择Qspring直接提供了对sessionFactory的封装,你只需要注册一个spring自己的类Q给它提供必ȝ属性,它会q回一个org.springframework.orm.hibernate.HibernateTemplateQ这个类装了add、del{操作,它的装E度相当高,通过它来~写hibernate应用非常单。但是问题出来了Q我们该如何选择Q?BR> 表面上看Q用spring自己的库无疑更加单,但是h意,spring是一个轻量的框Ӟ所谓轻量Q一个重要特征就是无侵入性,也就是你使用q套框架Q不会被它绑定,被spring理的类Q应该不需要用它的接口和抽象c,q样你的pȝ不会对spring产生依赖。但是如果你使用了spring装的方式去操作hibernateQ就必须l承org.springframework.orm.hibernate.support.HibernateDaoSupportc,q导致了l定。所以做q样的选择是有点痛苦的Q如果有一天spring框架不存在了Q你的代码怎么升l护Q具体问题只能具体分析,在我们的应用中,完全使用了spring装的HibernateTemplateQ它太好用了Q所以容易上瘾?BR> 假设我们有一张student表,l构很简单:
id 自动增长
name varchar(40)
password varchar(32)
grade int(4) q
sex Boolean 性别(true为男Qfalse为女)
设计一个StudentcL映射q张表:
/*
* 创徏日期 2005-3-17
*/
package net.bromon.spring.examer.pojo;
/**
* @author Bromon
*/
public class Student
{
private int id;
private String name;
private String password;
private int grade;//q
private boolean sex;
getsetҎ(gu)……?
}
~写Student.hbm.xmlQ让hibernate知道如何d联student表和Studentc,该文件和Student.java在同一目录Q?/P>
<hibernate-mapping>
<class name="net.bromon.spring.examer.pojo.Student" table="student">
<id name="id" column="id">
<generator class="identity"/>
</id>
<property name="name" column="name" />
<property name="password" column="password" />
<property name="grade" column="grade" />
<property name="sex" column="sex" />
</class>
</hibernate-mapping>
然后我们可以在spring中配|sessionFactoryQ?/P>
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
<property name="mappingDirectoryLocations">
<list>
<value>classpath:/netbromonspringexamerpojo</value>
</list>
</property>
</bean>
其中引用了我们之前注册过的dataSourceQmappingDirectoryLocations属性指明了.hbm.xml文g在哪里\径,该文件夹下面?hbm.xml文g会被全部加蝲?BR> 一切都准备qAQ现在我们要加入一个StudentManagerc,来进行增删查改的操作Q?BR>/*
* 创徏日期 2005-3-17
*/
package net.bromon.spring.examer.student;
import net.bromon.spring.examer.pojo.Student;
import org.springframework.orm.hibernate.HibernateTemplate;
import org.springframework.orm.hibernate.LocalSessionFactoryBean;
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
/**
* @author Bromon
*/
public class StudentManager extends HibernateDaoSupport
{
private LocalSessionFactoryBean sessionFactory;
private HibernateTemplate ht;
public StudentManager()
{
this.ht=super.getHibernateTemplate();
}
public void add(Student s)
{
ht.save(s);//插入一条数据只需要这一行代?
}
}
该类只演CZ如何增加一个StudentQHibernateTemplateq封装了很多有用的方法,h阅spring文档。StudentManager中的sessionFactory是由spring注入的,但是StudentManagerq没有对sessionFactory做Q何的处理Q这是因为所有的处理都被HibernateDaoSupport.getHibernateTemplate()装。整个StudentManager中也看不CQ何的异常处理Q他们也都被基类装了?BR> 最后一个步骤就是在spring中注册StudentMangerQ然后向它注入sessionFactoryQ?/P>
<bean id="studentManager" class="net.bromon.spring.examer.student.StudentManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
所有的配置都完成了Q下面做单元试Q?/P>
/*
* 创徏日期 2005-3-17
*/
package net.bromon.spring.examer.student.test;
import java.io.FileInputStream;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import net.bromon.spring.examer.pojo.Student;
import net.bromon.spring.examer.student.StudentManager;
import junit.framework.TestCase;
/**
* @author Bromon
*/
public class TestStudentManager extends TestCase {
public void testAdd()
{
try
{
ApplicationContext context =new ClassPathXmlApplicationContext("springConfig.xml");
Student s=new Student();
s.setName("bromon");
s.setPassword("123");
s.setGrade(3);
s.setSex(true);
((StudentManager)context.getBean("studentManager")).add(s);
}catch(Exception e)
{
e.printStackTrace();
}
}
}
Spring已经hibernate的操作简化到了非帔R的程度,最关键的是整个开发可以由设计来驱动,如果一个团队对spring有够的熟?zhn)Q那么完全可以由设计师规划所有的c,整理清楚cM间的关系Q写成配|文Ӟ然后~写hibernate映射文gQ将数据表与pojo兌Q成员就可以完全在设计方案内工作Q利用spring装好的hibernate模版Q开发v来速度非常快,调试也很Ҏ(gu)。它能够解决如何在团队内贯彻设计Ҏ(gu)的问题?BR> ׃本文不讲解hibernate的用,所以相兛_容请查阅hibernate文档?BR>四、Spring中的事务控制
Spring和EJB一P提供了两U事务管理方式:~程式和声明式。在考试pȝ中我们将使用声明式的事务理Q这是spring推荐的做法。用这U方式可以体验到spring的强大便P而且我们无须在DaocM~写MҎ(gu)的代码,只需要通过配置文g可以让普通的javacd载到事务理中,q个意义是很重大的?BR> Spring中进行事务管理的通常方式是利用AOPQ面向切片编E)的方式,为普通javacd装事务控Ӟ它是通过动态代理实现的Q由于接口是延迟实例化的Qspring在这D|间内通过拦截器,加蝲事务切片。原理就是这P具体l节请参考jdk中有兛_态代理的文档。本文主要讲解如何在spring中进行事务控制?BR> 动态代理的一个重要特征是Q它是针Ҏ(gu)口的Q所以我们的dao要通过动态代理来让spring接管事务Q就必须在dao前面抽象Z个接口,当然如果没有q样的接口,那么spring会用CGLIB来解决问题,但这不是spring推荐的方式,我们也不做讨论?BR> 参照前面的例子,我们为StudentManager.java定义一个接口,它的内容如下Q?/P>
/*
* 创徏日期 2005-3-25
*/
package org.bromon.spring.examer.student;
import java.util.List;
import org.bromon.spring.examer.pojo.Student;
/**
* @author Bromon
*/
public interface StudentManagerInterface
{
public void add(Student s);
public void del(Student s);
public void update(Student s);
public List loadAll();
public Student loadById(int id);
}
StudentManager也应该做Z改,实现该接口:
public class StudentManager extends HibernateDaoSupport implements StudentManagerInterface
现在需要修攚w|文Ӟ用于定义Hibrenate适用的事务管理器Qƈ且把sessionFactory注入q去Q同时还需要通过注册一个DefaultTransactionAttribute对象Q来指出事务{略。其中sessionFactory的定义已l在本文的第三章中说明?BR> 首先定义一个Hibernate的事务管理器Q让它来理sessionFactoryQ?BR><bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
下面定义事务理{略Q我们希望把{略定义在方法这个别上Q提供最大的灉|性,本例中将addҎ(gu)定义为:PROPAGATION_REQUIRES_NEWQ这可以保证它将始终q行在一个事务中?/P>
<bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<props>
<prop key="add">
PROPAGATION_REQUIRES_NEW
</prop>
</props>
</property>
</bean>
我们不仅可以为addҎ(gu)定义事务{略,q可以定义事务隔ȝ度和回滚{略,他们以逗号隔开,比如我们的add事务可以定义?
<prop key="add">
PROPAGATION_REQUIRES_NEW,-ExamerException
</prop>
q个事务{略表示addҎ(gu)会独占一个事务,当事务过E中产生ExamerException异常Q事务会回滚?BR> Add/update/del都是写入Ҏ(gu)Q对于selectQ读取)Ҏ(gu)Q我们可以指定较为复杂的事务{略Q比如对于loadAll()Ҏ(gu)Q?BR>
<prop key=”loadAll?gt;
PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly
</prop>
该事务的含义为,loadAllҎ(gu)支持事务Q不会读取未提交的数据,它的数据为只读(可提高执行速度Q?BR> 如你所见,我们的StudentManagerInterface接口中还有一个loadById(int id)Ҏ(gu)Q也许我们将来还会有很多的loadByXXXX的方法,N要一一Z们指定事务策略?太烦ZQ他们应该和loadAll()一P所以我们可以用通配W,定义所有的loadXXXXҎ(gu)Q?/P>
<prop key=”load*?gt;
PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly
</prop>
现在可以定义事务理器:
<bean id="studentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target">
<ref bean="studentManager"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
q个bean的外观是一个接?StudentManagerInterface)Q我们指Z它的具体实现(studentManager)Q而且为它l定了事务策略。在客户端用的时候,获得对象是StudentManagerInterfaceQ所有的操作都是针对q个接口的。测试代码ƈ没有改变Q我们虽然修改了很多地方Q加入了事务控制Q但是客Lq没有受到媄响,q也体现了spring的一些优ѝ测试代码如下:
public void testAdd()
{
ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");
StudentManager sm=(StudentManager)ctx.getBean("studentManager");
Student s=new Student();
s.setId(1);
s.setName("bromon");
s.setPassword("123");
s.setGrade(1);
s.setSex(0);
sm.add(s);
}
通过以上的代码可以看出,spring可以单的把普通的java classU_事务理Q声明性的事务操作h也很Ҏ(gu)。有了spring之后Q声明性事务不再是EJB独有Q我们不必ؓ了获得声明性事务的功能而去忍受EJB带来的种U不ѝ?BR>我所使用的mysql是不支持事务的,你可以更换用PostgreSQLQ有了spring+hibernateQ更换dbq不像以前那h怖了Q步骤很单:
1?dPostgreSQL的jdbc驱动
2?修改dataSource配置Q包括驱动名U、url、帐受密?BR>3?修改sessionFactory的数据库dailet为net.sf.hibernate.dialect.PostgreSQLDialect
4?修改hbm.xml中的主键生成{略为increment
所有的修改都在配置文g中完成,业务代码不需要Q何修改,我很满意QHow about u?
附A pring中的所有事务策?BR> PROPAGATION_MANDATORY
PROPAGATION_NESTED
PROPAGATION_NEVER
PROPAGATION_NOT_SUPPORTED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED_NEW
PROPAGATION_SUPPORTS
附B Spring中所有的隔离{略Q?BR> ISOLATION_DEFAULT
ISOLATION_READ_UNCOMMITED
ISOLATION_COMMITED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE