??xml version="1.0" encoding="utf-8" standalone="yes"?>一本色道久久88—综合亚洲精品
,久久精品国产亚洲精品2020,久久精品国产精品亚洲 http://www.tkk7.com/xixidabao/category/15380.htmlGROW WITH JAVA zh-cn Sat, 21 Apr 2007 02:48:12 GMT Sat, 21 Apr 2007 02:48:12 GMT 60 ?Spring 更好地处?Struts 动作三种整合 Struts 应用E序?Spring 的方?/title> http://www.tkk7.com/xixidabao/archive/2007/04/21/112404.htmlJAVA之\ JAVA之\ Sat, 21 Apr 2007 02:43:00 GMT http://www.tkk7.com/xixidabao/archive/2007/04/21/112404.html Z?Spring q么?jin)不P
Spring 的创立?Rod Johnson 以一U批判的眼光看待 Java™ 企业软g开发,q且提议很多企业N都能够通过战略C?IOC 模式Q也UC依赖注入Q来解决。当 Rod 和一个具有奉献精的开放源码开发者团队将q个理论应用于实跉|Q结果就产生?Spring 框架。简a之,Spring 是一个轻型的容器Q利用它可以使用一个外?XML 配置文g方便地将对象q接在一赗每个对象都可以通过昄一?JavaBean 属性收C个到依赖对象的引用,留给(zhn)的单Q务就只是在一?XML 配置文g中把它们q接好?/p>
IOC ?Spring
IOC 是一U应用E序逻辑外在化的设计模式Q所以它是被注入而不是被写入客户Z码中。将 IOC 与接口编E应用结合,像 Spring 框架那样Q生了(jin)一U架构,q种架构能够减少客户机对特定实现逻辑的依赖。请参阅 参考资?/u> ?jin)解更多关?IOC ?Spring 的信息?/p>
依赖注入是一个强大的Ҏ(gu),但是 Spring 框架能够提供更多Ҏ(gu)。Spring 支持可插拔的事务理器,可以l?zhn)的事务处理提供更q泛的选择范围。它集成?jin)领先的持久性框Ӟq且提供一个一致的异常层次l构。Spring q提供了(jin)一U用面向方面代码代替正常的面向对象代码的简单机制?/p>
Spring AOP 允许(zhn)?em>拦截?/em> 在一个或多个执行点上拦截应用E序逻辑。加强应用程序在拦截器中的日志记录逻辑?x)生一个更可读的、实用的代码基础Q所以拦截器q泛用于日志记录。?zhn)很快׃?x)看到Qؓ(f)?jin)处理横切关注点QSpring AOP 发布?jin)它自己的拦截器Q?zhn)也可以编写(zhn)自己的拦截器?/p>
整合 Struts ?Spring
?Struts 怼QSpring 可以作ؓ(f)一?MVC 实现。这两种框架都具有自q优点和缺点,管大部分h同意 Struts ?MVC 斚w仍然是最好的。很多开发团队已l学?x)在旉紧迫的时候利?Struts 作ؓ(f)构造高品质软g的基。Struts h如此大的推动力,以至于开发团队宁愿整?Spring 框架的特性,而不愿意转换?Spring MVC。没必要q行转换Ҏ(gu)来说是一个好消息。Spring 架构允许(zhn)将 Struts 作ؓ(f) Web 框架q接到基?Spring 的业务和持久层。最后的l果是现在一切条仉具备?jin)?/p>
在接下来的小H门中,(zhn)将?x)?jin)解到三种?Struts MVC 整合?Spring 框架的方法。我揭C每U方法的~陷q且Ҏ(gu)它们的优炏V?一旦?zhn)了(jin)解到所有三U方法的作用Q我会(x)向?zhn)展示一个o(h)人兴奋的应用E序Q这个程序用的是这三种Ҏ(gu)中我最喜欢的一U?/p>
三个窍?/font>
接下来的每种整合技术(或者窍门)(j)都有自己的优点和特点。我偏爱其中的一U,但是我知道这三种都能够加深?zhn)?Struts ?Spring 的理解。在处理各种不同情况的时候,q将l?zhn)提供一个广阔的选择范围。方法如下:(x)
使用 Spring ?ActionSupport
cL?Structs
使用 Spring ?DelegatingRequestProcessor
覆盖 Struts ?RequestProcessor
?Struts Action
理委托l?Spring 框架
装蝲应用E序环境
无论(zhn)用哪U技术,都需要?Spring ?ContextLoaderPlugin
?Struts ?ActionServlet
装蝲 Spring 应用E序环境。就像添加Q何其他插件一P单地向?zhn)?struts-config.xml 文gd该插Ӟ如下所C:(x)
<plug-in className=
"org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property=
"contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>
前面已经提到q,?下蝲 部分Q?zhn)能够扑ֈq三个完全可使用的例子的完整源代码。每个例子都Z个书c搜索应用程序提供一U不同的 Struts ?Spring 的整合方法。?zhn)可以在这里看C子的要点Q但是?zhn)也可以下载应用程序以查看所有的l节?/p>
H门 1. 使用 Spring ?ActionSupport
手动创徏一?Spring 环境是一U整?Struts ?Spring 的最直观的方式。ؓ(f)?jin)它变得更单,Spring 提供?jin)一些帮助。ؓ(f)?jin)方便地获?Spring 环境Q?code>org.springframework.web.struts.ActionSupport cL供了(jin)一?getWebApplicationContext()
Ҏ(gu)。?zhn)所做的只是?Spring ?ActionSupport
而不?Struts Action
cL展?zhn)的动作,如清?1 所C:(x)
清单 1. 使用 ActionSupport 整合 Struts
package ca.nexcel.books.actions;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import org.springframework.context.ApplicationContext;
import org.springframework.web.struts.ActionSupport;
import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;
public class SearchSubmit extends ActionSupport { |(1)
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
DynaActionForm searchForm = (DynaActionForm) form;
String isbn = (String) searchForm.get("isbn");
//the old fashion way
//BookService bookService = new BookServiceImpl();
ApplicationContext ctx =
getWebApplicationContext(); |(2)
BookService bookService =
(BookService) ctx.getBean("bookService"); |(3)
Book book = bookService.read(isbn.trim());
if (null == book) {
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,new ActionError
("message.notfound"));
saveErrors(request, errors);
return mapping.findForward("failure") ;
}
request.setAttribute("book", book);
return mapping.findForward("success");
}
}
让我们快速思考一下这里到底发生了(jin)什么。在 (1) 处,我通过?Spring ?ActionSupport
c而不?Struts ?Action
c进行扩展,创徏?jin)一个新?Action
。在 (2) 处,我?getWebApplicationContext()
Ҏ(gu)获得一?ApplicationContext
。ؓ(f)?jin)获得业务服务,我用?(2) 处获得的环境?(3) 处查找一?Spring bean?/p>
q种技术很单ƈ且易于理解。不q的是,它将 Struts 动作?Spring 框架耦合在一赗如果?zhn)x(chng)换掉 SpringQ那么?zhn)必须重写代码。ƈ且,׃ Struts 动作不在 Spring 的控制之下,所以它不能获得 Spring AOP 的优ѝ当使用多重独立?Spring 环境Ӟq种技术可能有用,但是在大多数情况下,q种Ҏ(gu)不如另外两种Ҏ(gu)合适?/p>
H门 2. 覆盖 RequestProcessor
?Spring ?Struts 动作中分L一个更巧妙的设计选择。分ȝ一U方法是使用 org.springframework.web.struts.DelegatingRequestProcessor
cL覆盖 Struts ?RequestProcessor
处理E序Q如清单 2 所C:(x)
清单 2. 通过 Spring ?DelegatingRequestProcessor q行整合
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean name="searchForm"
type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="isbn" type="java.lang.String"/>
</form-bean>
</form-beans>
<global-forwards type="org.apache.struts.action.ActionForward">
<forward name="welcome" path="/welcome.do"/>
<forward name="searchEntry" path="/searchEntry.do"/>
<forward name="searchSubmit" path="/searchSubmit.do"/>
</global-forwards>
<action-mappings>
<action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
<action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
<action path="/searchSubmit"
type="ca.nexcel.books.actions.SearchSubmit"
input="/searchEntry.do"
validate="true"
name="searchForm">
<forward name="success" path="/WEB-INF/pages/detail.jsp"/>
<forward name="failure" path="/WEB-INF/pages/search.jsp"/>
</action>
</action-mappings>
<message-resources parameter="ApplicationResources"/>
<controller processorClass="org.springframework.web.struts.
DelegatingRequestProcessor"/> |(1)
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>
</struts-config>
我利用了(jin) <controller>
标记来用 DelegatingRequestProcessor
覆盖默认?Struts RequestProcessor
。下一步是在我?Spring 配置文g中注册该动作Q如清单 3 所C:(x)
清单 3. ?Spring 配置文g中注册一个动?/strong>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>
<bean name="/searchSubmit"
class="ca.nexcel.books.actions.SearchSubmit"> |(1)
<property name="bookService">
<ref bean="bookService"/>
</property>
</bean>
</beans>
注意Q在 (1) 处,我用名U属性注册了(jin)一?beanQ以匚w struts-config 动作映射名称?code>SearchSubmit 动作揭示?jin)一?JavaBean 属性,允许 Spring 在运行时填充属性,如清?4 所C:(x)
清单 4. h JavaBean 属性的 Struts 动作
package ca.nexcel.books.actions;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;
public class SearchSubmit extends Action {
private BookService bookService;
public BookService getBookService() {
return bookService;
}
public void setBookService(BookService bookService) { | (1)
this.bookService = bookService;
}
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
DynaActionForm searchForm = (DynaActionForm) form;
String isbn = (String) searchForm.get("isbn");
Book book = getBookService().read(isbn.trim()); |(2)
if (null == book) {
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));
saveErrors(request, errors);
return mapping.findForward("failure") ;
}
request.setAttribute("book", book);
return mapping.findForward("success");
}
}
在清?4 中,(zhn)可以了(jin)解到如何创徏 Struts 动作。在 (1) 处,我创Z(jin)一?JavaBean 属性?code>DelegatingRequestProcessor自动地配|这U属性。这U设计 Struts 动作q不知道它正?Spring 理Qƈ且(zhn)能够利?Sping 的动作管理框架的所有优炏V由于?zhn)?Struts 动作注意不到 Spring 的存在,所以?zhn)不需要重写?zhn)?Struts 代码可以用其他控制反转容器来替换?Spring?/p>
DelegatingRequestProcessor
Ҏ(gu)的确比第一U方法好Q但是仍然存在一些问题。如果?zhn)使用一个不同的 RequestProcessor
Q则需要手动整?Spring ?DelegatingRequestProcessor
。添加的代码?x)造成l护的麻?ch)ƈ且将来?x)降低(zhn)的应用E序的灵zL。此外,q有q一些用一pd命o(h)来代?Struts RequestProcessor
的传闅R?q种改变会(x)对这U解x(chng)法的使用寿命造成负面的媄(jing)响?/p>
H门 3. 动作管理委托给 Spring
一个更好的解决Ҏ(gu)是将 Strut 动作理委托l?Spring。?zhn)可以通过?struts-config
动作映射中注册一个代理来实现。代理负责在 Spring 环境中查?Struts 动作。由于动作在 Spring 的控制之下,所以它可以填充动作?JavaBean 属性,qؓ(f)应用诸如 Spring ?AOP 拦截器之cȝҎ(gu)带来了(jin)可能?
清单 5 中的 Action
cM清单 4 中的相同。但?struts-config 有一些不同:(x)
清单 5. Spring 整合的委托方?/strong>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean name="searchForm"
type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="isbn" type="java.lang.String"/>
</form-bean>
</form-beans>
<global-forwards type="org.apache.struts.action.ActionForward">
<forward name="welcome" path="/welcome.do"/>
<forward name="searchEntry" path="/searchEntry.do"/>
<forward name="searchSubmit" path="/searchSubmit.do"/>
</global-forwards>
<action-mappings>
<action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
<action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
<action path="/searchSubmit"
type="org.springframework.web.struts.DelegatingActionProxy" |(1)
input="/searchEntry.do"
validate="true"
name="searchForm">
<forward name="success" path="/WEB-INF/pages/detail.jsp"/>
<forward name="failure" path="/WEB-INF/pages/search.jsp"/>
</action>
</action-mappings>
<message-resources parameter="ApplicationResources"/>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property
property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>
</struts-config>
清单 5 是一个典型的 struts-config.xml 文gQ只有一个小的差别。它注册 Spring 代理cȝ名称Q而不是声明动作的cdQ如Q?Q处所C。DelegatingActionProxy cM用动作映名U查?Spring 环境中的动作。这是我们使用 ContextLoaderPlugIn
声明的环境?/p>
一?Struts 动作注册Z?Spring bean 是非常直观的Q如清单 6 所C。我利用动作映射使用 <bean>
标记的名U属性(在这个例子中?"/searchSubmit
"Q简单地创徏?jin)一?bean。这个动作的 JavaBean 属性像M Spring bean 一栯填充Q?
清单 6. ?Spring 环境中注册一?Struts 动作
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>
<bean name="/searchSubmit"
class="ca.nexcel.books.actions.SearchSubmit">
<property name="bookService">
<ref bean="bookService"/>
</property>
</bean>
</beans>
动作委托的优?/font>
动作委托解决Ҏ(gu)是这三种Ҏ(gu)中最好的。Struts 动作不了(jin)?SpringQ不对代码作M改变可用于?Spring 应用E序中?code>RequestProcessor 的改变(sh)?x)?jing)响它Qƈ且它可以利用 Spring AOP Ҏ(gu)的优点?
动作委托的优点不止如此。一旦让 Spring 控制(zhn)的 Struts 动作Q?zhn)可以?Spring l动作补充更强的zd。例如,没有 Spring 的话Q所有的 Struts 动作都必LU程安全的。如果?zhn)讄?<bean>
标记?singleton 属性ؓ(f)“false”Q那么不用何种Ҏ(gu)Q?zhn)的应用程序都在每一个请求上有一个新生成的动作对象。?zhn)可能不需要这U特性,但是把它攑֜(zhn)的工具׃也很好。?zhn)也可以利?Spring 的生命周期方法。例如,当实例化 Struts 动作Ӟ<bean>
标记?init-method 属性被用于q行一个方法。类似地Q在从容器中删除 bean 之前Qdestroy-method 属性执行一个方法。这些方法是理昂贵对象的好办法Q它们以一U与 Servlet 生命周期相同的方式进行管理?/p>
拦截 Struts
前面提到q,通过?Struts 动作委托l?Spring 框架而整?Struts ?Spring 的一个主要的优点是:(x)(zhn)可以将 Spring ?AOP 拦截器应用于(zhn)的 Struts 动作。通过?Spring 拦截器应用于 Struts 动作Q?zhn)可以用最的代h(hun)处理横切x(chng)炏V?/p>
虽然 Spring 提供很多内置拦截器,但是我将向?zhn)展示如何创徏自己的拦截器q把它应用于一?Struts 动作。ؓ(f)?jin)用拦截器Q?zhn)需要做三g事:(x)
创徏拦截器?
注册拦截器?
声明在何处拦截代码?
q看h非常单的几句话却非常强大。例如,在清?7 中,我ؓ(f) Struts 动作创徏?jin)一个日志记录拦截器?q个拦截器在每个Ҏ(gu)调用之前打印一句话Q?/p>
清单 7. 一个简单的日志记录拦截?/strong>
package ca.nexcel.books.interceptors;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class LoggingInterceptor implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("logging before!");
}
}
q个拦截器非常简单?code>before() Ҏ(gu)在拦截点中每个方法之前运行。在本例中,它打印出一句话Q其实它可以做?zhn)惛_的Q何事。下一步就是在 Spring 配置文g中注册这个拦截器Q如清单 8 所C:(x)
清单 8. ?Spring 配置文g中注册拦截器
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>
<bean name="/searchSubmit"
class="ca.nexcel.books.actions.SearchSubmit">
<property name="bookService">
<ref bean="bookService"/>
</property>
</bean>
<!-- Interceptors -->
<bean name="logger"
class="ca.nexcel.books.interceptors.LoggingInterceptor"/> |(1)
<!-- AutoProxies -->
<bean name="loggingAutoProxy"
class="org.springframework.aop.framework.autoproxy.
BeanNameAutoProxyCreator"> |(2)
<property name="beanNames">
<value>/searchSubmit</valuesgt; |(3)
</property>
<property name="interceptorNames">
<list>
<value>logger</value> |(4)
</list>
</property>
</bean>
</beans>
(zhn)可能已l注意到?jin),清?8 扩展?清单 6 中所C的应用E序以包含一个拦截器。具体细节如下:(x)
?(1) 处,我注册了(jin)q个拦截器?
?(2) 处,我创Z(jin)一?bean 名称自动代理Q它描述如何应用拦截器。还有其他的Ҏ(gu)定义拦截点,但是q种Ҏ(gu)常见而简ѝ?
?(3) 处,我将 Struts 动作注册为将被拦截的 bean。如果?zhn)惌拦截其他?Struts 动作Q则只需要在 "beanNames" 下面创徏附加?<value>
标记?
?(4) 处,当拦截发生时Q我执行?jin)?(1) 处创建的拦截?bean 的名U。这里列出的所有拦截器都应用于“beanNames”?
是q样。就像这个例子所展示的,?zhn)?Struts 动作|于 Spring 框架的控制之下,为处理?zhn)?Struts 应用E序提供?jin)一pd全新的选择。在本例中,使用动作委托可以L地利?Spring 拦截器提?Struts 应用E序中的日志记录能力?/p>
]]>Hibernate 的原理与配置快速入?/title> http://www.tkk7.com/xixidabao/archive/2006/05/17/46596.htmlJAVA之\ JAVA之\ Wed, 17 May 2006 03:46:00 GMT http://www.tkk7.com/xixidabao/archive/2006/05/17/46596.html 看完本文后,我相信你对什么是ORMQ对?关系映射Q以?qing)它的优点?x)有一个深ȝ认识Q我们先通过一个简单的例子开始来展现它的威力?br /> 正如一些传l的l典计算机文章大都会(x)通过一个“hello,world”的例子开始讲解一P我们也不例外Q我们也从一个相对简单的例子来阐qHibernate的开发方法,但如果要真正阐述Hibernate的一些重要思想Q仅仅靠在屏q上打印一些字W是q远不够的,在我们的CZE序中,我们创Z些对象,q将其保存在数据库中Q然后对它们q行更新和查询?br />阅读D
“Hello World?/font> “Hello world”示例程序让(zhn)对Hibernate有一个简单的认识?/strong> 理解Hibernate的架?/font> 介绍Hibernate接口的主要功能?/td> 核心(j)接口 Hibernate?个核?j)接口,通过q几个接口开发h员可以存储和获得持久对象Qƈ且能够进行事务控?/td> 一个重要的术语QType Type是Hibernate发明者发明的一个术语,它在整个构架中是一个非常基、有着强大功能的元素,一个Type对象能将一个Javacd映射到数据库中一个表的字D中厅R?/td> {略接口 Hibernate与某些其它开源Y件不同的q有一点――高度的可扩展性,q通过它的内置{略机制来实现?/td> 基础配置 Hibernate可以配置成可在Q何Java环境中运行,一般说来,它通常被用?Q?层的C/S模式的项目中Qƈ被部|在服务端?/td> 创徏一个SessionFactory对象 要创Z个SessionFactory对象Q必dHibernate初始化时创徏一个Configurationcȝ实例Qƈ已写好的映文件交由它处理?/td> “Hello World?/strong> Hibernate应用E序定义?jin)一些持久类Qƈ且定义了(jin)q些cM数据库表格的映射关系。在我们q个“Hello world”示例程序中包含?jin)一个类和一个映文件。让我们看看q个单的持久cd含有一些什么?映射文g是怎样定义的?另外Q我们该怎样用Hibernate来操作这个持久类?br /> 我们q个单示例程序的目的是将一些持久类存储在数据库中,然后从数据库取出来,q将其信息正文显C给用户。其中Message正是一个简单的持久c:(x)Q它包含我们要显C的信息Q其源代码如下:(x) 列表1 Message.Java 一个简单的持久c?br />
package hello; public class Message { private Long id; private String text; private Message nextMessage; private Message() {} public Message(String text) { this.text = text; } public Long getId() { return id; } private void setId(Long id) { this.id = id; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Message getNextMessage() { return nextMessage; } public void setNextMessage(Message nextMessage) { this.nextMessage = nextMessage; } }
MessagecL三个属性:(x)Message的id 、消息正文、以?qing)一个指向下一条消息的指针。其中id属性让我们的应用程序能够唯一的识别这条消息,通常它等同于数据库中的主键,如果多个Messagecȝ实例对象拥有相同的idQ那它们代表数据库某个表的同一个记录。在q里我们选择?jin)长整型作?f)我们的id|但这不是必需的。Hibernate允许我们使用L的类型来作ؓ(f)对象的id|在后面我们会(x)Ҏ(gu)作详l描q?br /> 你可能注意到Messagecȝ代码cM于JavaBean的代码风|q且它有一个没有参数的构造函敎ͼ在我们以后的代码中我(h)l用这U风格来~写持久cȝ代码?br /> Hibernate?x)自动管理Messagecȝ实例Qƈ通过内部机制使其持久化,但实际上Message对象q没有实CQ何关于Hibernate的类或接口,因此我们也可以将它作Z个普通的JavacL使用Q?br />Message message = new Message("Hello World"); System.out.println( message.getText() );
以上q段代码正是我们所期望的结果:(x)它打印“hello world”到屏幕上。但qƈ不是我们的最l目标;实际上Hibernate与诸如EJB容器q样的环境在持久层实现的方式上有很大的不同。我们的持久c?Messagec?可以用在与容器无关的环境中,不像EJB必须要有EJB容器才能执行。ؓ(f)?jin)能更清楚地表现q点Q以下代码将我们的一个新消息保存到数据库中去Q?br />Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); Message message = new Message("Hello World"); session.save(message); tx.commit(); session.close();
以上q段代码调用?jin)Hibernate的Session和Transaction接口Q关于getSessionFactory()Ҏ(gu)我们会(x)马上提到Q。它相当于我们执行了(jin)以下SQL语句Q?br />insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) values (1, 'Hello World', null)
在以上的SQL语句中,MESSAGE_ID字段到底被初始化成了(jin)什么值呢Q由于我们ƈ没有在先前的代码中ؓ(f)message对象的id属性赋与初始|那它是否为null呢?实际上Hibernate对id属性作?jin)特D处理:(x)׃它是一个对象的唯一标识Q因此当我们q行save()调用ӞHibernate?x)?f)它自动赋予一个唯一的|我们在后面内容中讲q它是如何生成这个值的Q?br /> 我们假设你已l在数据库中创徏?jin)一个名为MESSAGE的表Q那么既然前面这D代码让我们Message对象存入?jin)数据库中,那么现在我们p它们一一取出来。下面这D代码将按照字母序Q将数据库中的所有Message对象取出来,q将它们的消息正文打印到屏幕上:(x)Session newSession = getSessionFactory().openSession(); Transaction newTransaction = newSession.beginTransaction(); List messages =newSession.find("from Message as m order by m.text asc"); System.out.println( messages.size() + " message(s) found:" ); for ( Iterator iter = messages.iterator(); iter.hasNext(); ) { Message message = (Message) iter.next(); System.out.println( message.getText() ); } newTransaction.commit(); newSession.close();
在以上这D代码中Q你可能被find()Ҏ(gu)的这个参数困扰着Q?from Message as m order by m.text asc"Q其实它是Hibernate自己定义的查询语aQ全U叫Hibernate Query Language(HQL)。通俗地讲HQL与SQL的关pd不多是方言与普通话之间的关p,咋一看,你会(x)觉得它有点类gSQL语句。其实在find()调用ӞHibernate?x)将q段HQL语言译成如下的SQL语句Q?br />select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID from MESSAGES m order by m.MESSAGE_TEXT asc
以下是q行l果Q?1 message(s) found: Hello World
如果你以前没有ORMQ对象-关系映射Q的开发经验,那你可能惛_代码的某个地方去Lq段SQL语句Q但在Hibernate中你可能?x)失望?x)它根本不存在Q所有就SQL语句都是Hibernate动态生成的? 也许你会(x)觉得q缺点什么,对!仅凭以上代码Hibernate是无法将我们的MessagecL久化的。我们还需要一些更多的信息Q这是映射定义表!q个表在Hibernate中是以XML格式来体现的Q它定义?jin)Messagecȝ属性是怎样与数据库中的MESSAGES表的字段q行一一对应的,列表2是这个示例程序的映射配置文g清单Q?br /> 列表2Q示例程序的对象Q关pL表 Q?xml version="1.0"?Q?br />Q?DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"Q?br />Qhibernate-mappingQ?br />Qclass name="hello.Message" table="MESSAGES"Q?br /> Qid name="id" column="MESSAGE_ID"Q?br /> Qgenerator class="increment"/Q?br /> Q?idQ?br /> Qproperty name="text" column="MESSAGE_TEXT"/Q?br /> Qmany-to-one name="nextMessage" cascade="all" column="NEXT_MESSAGE_ID"/Q?br />Q?classQ?br />Q?hibernate-mappingQ?
以上q个文档告诉Hibernate怎样MessagecL到MESSAGES表中Q其中Messagecȝid属性与表的MESSAGE_ID字段对应Qtext属性与表的MESSAGE_TEXT字段对应QnextMessage属性是一个多对一的关p,它与表中的NEXT_MESSAGE_ID相对应? 相对于有些开源项目来_(d)Hibernate的配|文件其实是很容易理解的。你可以LC改与l护它。只要你定义好了(jin)持久cM数据库中表字D늚对应关系p?jin),Hibernate?x)自动帮你生成SQL语句来对Message对象q行插入、更新、删除、查扑ַ作,你可以不写一句SQL语句Q甚至不需要懂得SQL语言Q?br /> 现在让我们做一个新的试验,我们先取出第一个Message对象Q然后修改它的消息正文,最后我们再生成一个新的Message对象Qƈ它作ؓ(f)W一个Message对象的下一条消息,其代码如下:(x) 列表3 更新一条消?br />Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); // 1 is the generated id of the first message Message message =(Message) session.load( Message.class, new Long(1) ); message.setText("Greetings Earthling"); Message nextMessage = new Message("Take me to your leader (please)"); message.setNextMessage( nextMessage ); tx.commit(); session.close();
以上q段代码在调用时QHibernate内部自动生成如下的SQL语句Q?br />select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID from MESSAGES m where m.MESSAGE_ID = 1 insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) values (2, 'Take me to your leader (please)', null) update MESSAGES set MESSAGE_TEXT = 'Greetings Earthling', NEXT_MESSAGE_ID = 2 where MESSAGE_ID = 1
当第一个Message对象的text属性和nextMessage被程序修Ҏ(gu)Q请注意Hibernate是如何检到q种变化Qƈ如何在数据库中自动对它更新的。这实际上是Hibernate的一个很有h(hun)值的特色Q我们把它称为“自动脏数据?hu)(g)”,Hibernate的这个特色得当我们修改一个持久对象的属性后Q不必显式地通知Hibernated它在数据库中q行更新。同L(fng)Q当W一个Message对象调用setNextMessage()Ҏ(gu)第二个Message对象作ؓ(f)它的下一条消息的引用ӞW二条消息会(x)无需调用save()Ҏ(gu)Q便可以自动C存在数据库中。这U特色被UCؓ(f)“联保存”,它也免去?jin)我们显式地对第二个Message对象调用save()Ҏ(gu)之苦?br /> 如果我们再运行先前的那段数据库中所有的Message对象都打印出来的代码Q那它的q行l果如下Q?br />2 message(s) found: Greetings Earthling Take me to your leader (please)
“Hello world”示例程序现在介l完毕。我们ȝ对Hibernate有了(jin)一个简单的认识Q下面我们将回过头来Q对Hibernate的主要API调用作一下简要的介绍Q?br />理解Hibernate的架?/strong> 当你想用Hibernate开发自qZ持久层的应用ӞW一件事情应当是熟?zhn)它的~程接口。Hibernate的API接口设计得尽量简z明?jin),以方便开发h员。然而实际上׃ORM的复杂性,它的API一般都不可能设计得很简单。但是别担心(j)Q你没有必要一下子?jin)解所有的Hibernate的API接口。下面这张图描述?jin)Hibernate在应用层和持久层中的一些重要的接口c:(x) 在上图中Q我们将应用层放在了(jin)持久层的上部Q实际上在传l的目中,应用层充当着持久层的一个客L(fng)角色。但对于一些简单的目来说Q应用层和持久层q没有区分得那么清楚Q这也没什么,在这U情况下你可以将应用层和持久层合q成?jin)一层?br /> 在上图中QHibernate的接口大致可以分Z下几U类型:(x) · 一些被用户的应用程序调用的Q用来完成基本的创徏、读取、更新、删除操作以?qing)查询操作的接口。这些接口是Hibernate实现用户E序的商业逻辑的主要接口,它们包括Session、Transaction和Query?br /> · Hibernate用来d诸如映射表这c配|文件的接口Q典型的代表有ConfigurationcR?br /> · 回调(Callback)接口。它允许应用E序能对一些事件的发生作出相应的操作,例如Interceptor、Lifecycle和Validatable都是q一cL口?br /> · 一些可以用来扩展Hibernate的映机制的接口Q例如UserType、CompositeUserType和IdentifierGenerator。这些接口可qL(fng)序来实现Q如果有必要Q?br /> Hibernate使用?jin)J2EE架构中的如下技术:(x)JDBC、JTA、JNDI。其中JDBC是一个支持关pL据库操作的一个基层;它与JNDI和JTA一L(fng)合,使得Hibernate可以方便地集成到J2EE应用服务器中厅R?br /> 在这里,我们不会(x)详细地去讨论Hibernate API接口中的所有方法,我们只简要讲一下每个主要接口的功能Q如果你想了(jin)解得更多的话Q你可以在Hibernate的源码包中的net.sf.hibernate子包中去查看q些接口的源代码。下面我们依ơ讲一下所有的主要接口Q?br /> 核心(j)接口 以下5个核?j)接口几乎在M实际开发中都会(x)用到。通过q些接口Q你不仅可以存储和获得持久对象,q且能够q行事务控制?br /> Session接口 Session接口对于Hibernate 开发h员来说是一个最重要的接口。然而在Hibernate中,实例化的Session是一个轻量的类Q创建和销毁它都不?x)占用很多资源。这在实际项目中实很重要,因ؓ(f)在客L(fng)序中Q可能会(x)不断地创Z?qing)销毁Session对象Q如果Session的开销太大Q会(x)l系l带来不良媄(jing)响。但值得注意的是Session对象是非U程安全的,因此在你的设计中Q最好是一个线E只创徏一个Session对象?br /> 在Hibernate的设计者的头脑中,他们session看作介于数据q接与事务管理一U中间接口。我们可以将session惌成一个持久对象的~冲区,Hibernate能检到q些持久对象的改变,q及(qing)时刷新数据库。我们有时也USession是一个持久层理器,因ؓ(f)它包含这一些持久层相关的操作,诸如存储持久对象x(chng)据库Q以?qing)从数据库从获得它们。请注意QHibernate 的session不同于JSP应用中的HttpSession。当我们使用sessionq个术语Ӟ我们指的是Hibernate中的sessionQ而我们以后会(x)HttpSesion对象UCؓ(f)用户session?br /> SessionFactory 接口 q里用到?jin)一个设计模式――工厂模式,用户E序从工厂类SessionFactory中取得Session的实例?br /> 令你感到奇怪的是SessionFactoryq不是轻量的!实际上它的设计者的意图是让它能在整个应用中׃n。典型地来说Q一个项目通常只需要一个SessionFactory够?jin),但是当你的项目要操作多个数据库时Q那你必Mؓ(f)每个数据库指定一个SessionFactory?br />SessionFactory在Hibernate中实际vC(jin)一个缓冲区的作用,它缓冲了(jin)Hibernate自动生成的SQL语句和一些其它的映射数据Q还~冲?jin)一些将来有可能重复利用的数据?br /> Configuration 接口 Configuration接口的作用是对Hibernateq行配置Q以?qing)对它进行启动。在Hibernate的启动过E中QConfigurationcȝ实例首先定位映射文档的位|,dq些配置Q然后创Z个SessionFactory对象?br /> 虽然Configuration接口在整个Hibernate目中只扮演着一个很的角色Q但它是启动hibernate时你所遇到的每一个对象?br /> Transaction 接口 Transaction接口是一个可选的APIQ你可以选择不用这个接口,取而代之的是Hibernate的设计者自己写的底层事务处理代码?Transaction接口是对实际事务实现的一个抽象,q些实现包括JDBC的事务、JTA中的UserTransaction、甚臛_以是CORBA事务。之所以这栯计是能让开发者能够用一个统一事务的操作界面,使得自己的项目可以在不同的环境和容器之间方便地移倹{?br /> Query和Criteria接口 Query接口让你方便地对数据库及(qing)持久对象q行查询Q它可以有两U表达方式:(x)HQL语言或本地数据库的SQL语句。Queryl常被用来绑定查询参数、限制查询记录数量,q最l执行查询操作?br /> Criteria接口与Query接口非常cMQ它允许你创建ƈ执行面向对象的标准化查询?br /> 值得注意的是Query接口也是轻量U的Q它不能在Session之外使用?br /> Callback 接口 当一些有用的事g发生时――例如持久对象的载入、存储、删除时QCallback接口?x)通知HibernateL收一个通知消息。一般而言QCallback接口在用L(fng)序中q不是必ȝQ但你要在你的项目中创徏审计日志Ӟ你可能会(x)用到它?br /> 一个重要的术语QType Hibernate的设计者们发明?jin)一个术语:(x)TypeQ它在整个构架中是一个非常基、有着强大功能的元素。一个Type对象能将一个Javacd映射到数据库中一个表的字D中去(实际上,它可以映到表的多个字段中去Q。持久类的所有属性都对应一个type。这U设计思想使用Hibernate有着高度的灵zL和扩展性?br /> Hibernate内置很多typecdQ几乎包括所有的Java基本cdQ例如Java.util.Currency、Java.util.calendar、byte[]和Java.io.Serializable?br /> 不仅如此QHibernateq支持用戯定义的typeQ通过实现接口UserType和接口CompositeUserTypeQ你可以加入自己的type。你可以利用q种特色让你的项目中使用自定义的诸如Address、Nameq样的typeQ这样你可以获得更大的便利Q让你的代码更优雅。自定义type在Hibernate中是一Ҏ(gu)?j)特Ԍ它的设计者鼓׃多多使用它来创徏一个灵zR优雅的目Q?br /> {略接口 Hibernate与某些其它开源Y件不同的q有一点――高度的可扩展性,q通过它的内置{略机制来实现。当你感觉到Hibernate的某些功能不I或者有某些~陷Ӟ你可以开发一个自q{略来替换它Q而你所要做的仅仅只是(h)承它的某个策略接口,然后实现你的新策略就可以?jin),以下是它的策略接口?x) · 主键的生?(IdentifierGenerator 接口) · 本地SQL语言支持 (Dialect 抽象c? · ~冲机制 (Cache 和CacheProvider 接口) · JDBC q接理 (ConnectionProvider接口) · 事务理 (TransactionFactory, Transaction, ?TransactionManagerLookup 接口) · ORM {略 (ClassPersister 接口) · 属性访问策?(PropertyAccessor 接口) · 代理对象的创?(ProxyFactory接口) HibernateZ上所列的机制分别创徏?jin)一个缺省的实现Q因此如果你只是要增强它的某个策略的功能的话Q只需单地l承q个cd可以?jin),没有必要从头开始写代码?br /> 以上是Hibernate的一些核?j)接口,但当我们真正开始用它进行开发时Q你的脑里可能M(x)有一个疑问:(x)我是通过什么方式,q从哪里取得Session的呢Q以下我们就解答q个问题?br /> 基础配置 现在回顾一下我们先前的内容Q我们写Z(jin)一个示例程序,q简要地讲解?jin)Hibernate的一些核?j)类。但要真正你的目q行hQ还有一件事必须要做Q配|。Hibernate可以配置成可在Q何Java环境中运行,一般说来,它通常被用?Q?层的C/S模式的项目中Qƈ被部|在服务端。在q种目中,W(xu)eb览器、或Java GUIE序充当者客L(fng)。尽我们的焦点主要是集中在多层web应用Q但实际上在一些基于命令行的应用中也可以用Hibernate。ƈ且,对Hibernate的配|在不同的环境下都会(x)不同QHibernateq行在两U环境下Q可理环境和不可管理环?br /> · 可管理环境――这U环境可理如下资源Q池资源理Q诸如数据库q接池和Q还有事务管理、安全定义。一些典型的J2EE服务器(JBoss、Weblogic、WebSphereQ已l实C(jin)q些?br /> · 不可理环境――只是提供了(jin)一些基本的功能Q诸如像Jetty或Tomcatq样的servlet容器环境。一个普通的Java桌面应用或命令行E序也可以认为是处于q种环境下。这U环境不能提供自动事务处理、资源管理或安全理Q这些都必须由应用程序自己来定义?br /> Hibernate的设计者们这两种环境设计?jin)一个统一的抽象界面,因此对于开发者来说只有一U环境:(x)可管理环境。如果实际项目是建立在诸如Tomcatq类不可理的环境中Ӟ那Hibernate会(x)使用它自q事务处理代码和JDBCq接池,使其变(sh)ؓ(f)一个可理环境?br />对于可管理的环境而言QHibernate?x)将自己集成在这U环境中。对于开发者而言Q你所要做的工作非常简单:(x)只需从一个ConfigurationcM创徏一个SessionFactorycd可以?jin)?br />创徏一个SessionFactory对象 Z(jin)能创Z个SessionFactory对象Q你必须在Hibernate初始化时创徏一个Configurationcȝ实例Qƈ已写好的映文件交由它处理。这PConfiguration对象可以创Z个SessionFactory对象Q当SessionFactory对象创徏成功后,Configuration对象没有用?jin),你可以简单地抛弃它。如下是CZ代码Q?br />Configuration cfg = new Configuration(); cfg.addResource("hello/Message.hbm.xml"); cfg.setProperties( System.getProperties() ); SessionFactory sessions = cfg.buildSessionFactory();
在以上代码中QMessage.hb.xmlq个映射文g的位|比较特D,它与当前的classpath相关。例如classpath包含当前目录Q那在上qC码中的Message.hbm.xml映射文g可以保存在当前目录下的hello目录中?br /> 作ؓ(f)一U约定,Hibernate的映文仉认以.htm.xml作ؓ(f)其扩展名。另一个约定是坚持为每一个持久类写一个配|文Ӟ想一惛_果你所有持久类的映写入一个单独的配置文g中的话,那这个配|文件肯定非常庞大,不易l护。但q里又出C(jin)一个新问题Q如果ؓ(f)每个cd一个配|文件的话,q么多的配置文g应该存放在哪里呢Q?br /> Hibernate推荐你将每个映射文g保存在与持久cȝ同的目录下,q且与持久类同名。例如我们第一个示例程序中的Message持久cL在hello目录下,那你必须在这个目录下存放名ؓ(f)Message.hbm.xml的映文件。这样一个持久类都有自己的一个映文Ӟ避免?jin)出现像struts目中的“struts-config.xml地狱”的情况。如果你不遵循这U规定,那你必须手动地用addResource()Ҏ(gu)一个个的映文件蝲入;但你如果遵@q种规定Q那你可以方便地用addClass()Ҏ(gu)同时持久类和它的映文件蝲入,以下是体现这U便利性的CZ代码Q?br />SessionFactory sessions = new Configuration() .addClass(org.hibernate.auction.model.Item.class) .addClass(org.hibernate.auction.model.Category.class) .addClass(org.hibernate.auction.model.Bid.class) .setProperties( System.getProperties() ) .buildSessionFactory();
当然QHibernate的映文件还有很多其它的配置选项Q比如数据库q接的设定,或是能够改变Hibernateq行时行为的一些设定。所有的讄可能是非常庞杂的Q以让你喘?sh)过气来Q但是不必担?j),因?f)Hibernate为绝大多数值都讑֮?jin)一个合理缺省|你只需要修改这些配|文件中的极一部分倹{?br /> 你可以通过以下几种方式来修改Hibernate的系l配|参敎ͼ(x) · 一个Java.util.Properties实例作ؓ(f)参数传给C(j)onfigurationcȝsetProperties()Ҏ(gu)?br /> · 在Hibernate启动时用Java –Dproperty=value的方式设|倹{?br /> · 在classpath可以扑ֈ的\径下创徏一个名为hibernate.properties的配|文件? · 在classpath可以扑ֈ的\径下创徏一个名为hibernate.cfg.xml的文Ӟq在ӞpropertyQ标{中定义属性倹{?br /> 以上是对Hibernate的一个大致介l,如果你想知道得更多,那本文还是远q不够的Q我陆l推出更多关于Hibernate的资料。但有一Ҏ(gu)毫无疑问的:(x)它的是一个非怼U的持久层解决Ҏ(gu)Q?br /> ]]>
վ֩ģ壺
鶹ƵѲ |
AVĻ |
պƷһ |
ĻƵ |
պƷӰһ |
һ߹ۿ |
Ʒ鶹av |
avƬ߹ۿ18Ů |
Ʒ߹ۿ |
뾫Ʒ˳ |
AVרAV
|
Aһ |
Ʒ߲ |
aƵ |
AVվ |
Ƶ߹ۿ |
ƷƵ߹ۿ |
Ůվѿվ |
߿ƬѲ˳Ƶ |
椸Ƶ߹ۿ |
Ƶ |
ƷŮþþ |
츾AV߲ |
þþþAVƬ |
ëƬѹۿ |
þӰԺ |
AëƬֻ |
ƷϵƵ
|
պƷר
|
AVһɫ |
ɫһëƬѿ |
þƬѹۿ |
99ѹƷ |
ƷƵһ |
mm1313Ʒִִ
|
һëƬ߲ |
ƷƷɫ |
Ʒ |
aŹavۺav |
ƷѾþþþùһ |
vƬ߹ۿƵվ |