??xml version="1.0" encoding="utf-8" standalone="yes"?>免费亚洲视频在线观看,久久夜色精品国产噜噜噜亚洲AV,亚洲美女激情视频http://www.tkk7.com/sutao/category/24688.html用文字记录学习的体验Q?/description>zh-cnWed, 21 Nov 2007 01:53:31 GMTWed, 21 Nov 2007 01:53:31 GMT60详细讲解在Hibernate中检索策略的应用http://www.tkk7.com/sutao/articles/161878.html苏醄苏醄Tue, 20 Nov 2007 07:59:00 GMThttp://www.tkk7.com/sutao/articles/161878.htmlhttp://www.tkk7.com/sutao/comments/161878.htmlhttp://www.tkk7.com/sutao/articles/161878.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/161878.htmlhttp://www.tkk7.com/sutao/services/trackbacks/161878.html详细讲解在Hibernate中检索策略的应用
 

  Hibernate的检?nobr oncontextmenu="return false;" onmousemove="kwM(1);" id="key1" onmouseover="kwE(event,1, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">{略包括cȝ别检索策略和兌U别索策略?/p>

  cȝ别检索策略有立即索和延迟索,默认的检索策略是立即索。在Hibernate映射文g中,通过?lt;不着class>上配|lazy属性来定索策略。对于Session的检索方式,cȝ别检索策略仅适用于loadҎQ也pQ对于get?qurey索,持久化对象都会被立即加蝲而不lazy是falseq是true.一般来_我们索对象就是要讉K它,因此立即索是通常的选择。由于loadҎ在检索不到对象时会抛出异常(立即索的情况下)Q因此我个hq不使用load索;而由?lt; class>中的lazy属性还影响到多对一及一对一的检索策略,因此使用loadҎ更没必要了?/div>

  兌U别索策略有立即索、gq检索和q切左外q接索。对于关联别检索,又可分ؓ一对多和多对多、多对一和一对一两种情况讨论?/p>

  一对多和多对多兌关系一般?lt; set>配置?lt; set>有lazy和outer-join属性,它们的不同取值绝对了索策略?/p>

  1Q立x索:q是一对多默认的检索策略,此时lazy=falseQouter-join=false.管q是默认的检索策略,但如果关联的集合是无用的Q那么就不要使用q种索方式?/p>

  2Qgq检索:此时lazy=trueQouter-join=falseQouter-join=true是无意义的)Q这是优先考虑的检索方式?/p>

  3Q迫切左外连接检索:此时 lazy=falseQouter-join=trueQ这U检索策略只适用于依靠id索方式(load、getQ,而不适用于query的集合检索(它会采用立即索策略)。相比于立即索,q种索策略减了一条sql语句Q但在Hibernate中,只能有一个配|成 outer-join=true.

  多对一和一对一索策略一般?lt; many-to-one>?lt; one-to-one>配置?lt; many-to-one>中需要配|的属性是 outer-joinQ同时还需要配|one端关联的< class>的lazy属性(配置的可不是< many-to-one>中的lazy哦)Q它们的l合后的索策略如下:

  1Q?outer-join=autoQ这是默认|如果lazy=true为gq检索,如果lazy=false切左外连接检索?/p>

  2Q?outer-join=trueQ无关于lazyQ都切左外连接检索?/p>

  3Q?outer-join=falseQ如果lazy=true为gq检索,否则为立x索?/p>

  可以看到Q在默认的情况下Qouter-join=autoQlazy=falseQ,对关联的one端对象Hibernate采用的迫切左外连接检索。依我看Q很多情况下Q我们ƈ不需要加载one端关联的对象Q很可能我们需要的仅仅是关联对象的idQ;另外Q如果关联对象也采用了迫切左外连接检索,׃出现select语句中有多个外连接表Q如果个数多的话会媄响检索性能Q这也是Z么Hibernate通过 hibernate.max_fetch_depth属性来控制外连接的深度。对于迫切左外连接检索,query的集合检索ƈ不适用Q它会采用立x索策略?/p>

  对于索策略,需要根据实际情况进行选择。对于立x索和延迟索,它们的优点在于select语句单(每张表一条语句)、查询速度快,~点在于兌表时需要多条select语句Q增加了讉K数据?/a>的频率。因此在选择x索和延迟索时Q可以考虑使用扚w索策略来减少select语句的数量(配置batch-size属性)。对于切左外q接索,优点在于select较少Q但~点是select语句的复杂度提高Q多表之间的兌会是很耗时的操作。另外,配置文g是死的,?nobr oncontextmenu="return false;" onmousemove="kwM(2);" id="key2" onmouseover="kwE(event,2, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">E序是活的,可以Ҏ需要在E序里显C的指定索策略(可能l常需要在E序中显C指定迫切左外连接检索)。ؓ了清楚检索策略的配置效果如何Q可以配|show_sql属性查看程序运行时Hibernate执行的sql语句?/p>



苏醄 2007-11-20 15:59 发表评论
]]>详细讲解在Hibernate中检索策略的应用http://www.tkk7.com/sutao/articles/161879.html苏醄苏醄Tue, 20 Nov 2007 07:59:00 GMThttp://www.tkk7.com/sutao/articles/161879.htmlhttp://www.tkk7.com/sutao/comments/161879.htmlhttp://www.tkk7.com/sutao/articles/161879.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/161879.htmlhttp://www.tkk7.com/sutao/services/trackbacks/161879.html详细讲解在Hibernate中检索策略的应用
 

  Hibernate的检?nobr oncontextmenu="return false;" onmousemove="kwM(1);" id="key1" onmouseover="kwE(event,1, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">{略包括cȝ别检索策略和兌U别索策略?/p>

  cȝ别检索策略有立即索和延迟索,默认的检索策略是立即索。在Hibernate映射文g中,通过?lt;不着class>上配|lazy属性来定索策略。对于Session的检索方式,cȝ别检索策略仅适用于loadҎQ也pQ对于get?qurey索,持久化对象都会被立即加蝲而不lazy是falseq是true.一般来_我们索对象就是要讉K它,因此立即索是通常的选择。由于loadҎ在检索不到对象时会抛出异常(立即索的情况下)Q因此我个hq不使用load索;而由?lt; class>中的lazy属性还影响到多对一及一对一的检索策略,因此使用loadҎ更没必要了?/div>

  兌U别索策略有立即索、gq检索和q切左外q接索。对于关联别检索,又可分ؓ一对多和多对多、多对一和一对一两种情况讨论?/p>

  一对多和多对多兌关系一般?lt; set>配置?lt; set>有lazy和outer-join属性,它们的不同取值绝对了索策略?/p>

  1Q立x索:q是一对多默认的检索策略,此时lazy=falseQouter-join=false.管q是默认的检索策略,但如果关联的集合是无用的Q那么就不要使用q种索方式?/p>

  2Qgq检索:此时lazy=trueQouter-join=falseQouter-join=true是无意义的)Q这是优先考虑的检索方式?/p>

  3Q迫切左外连接检索:此时 lazy=falseQouter-join=trueQ这U检索策略只适用于依靠id索方式(load、getQ,而不适用于query的集合检索(它会采用立即索策略)。相比于立即索,q种索策略减了一条sql语句Q但在Hibernate中,只能有一个配|成 outer-join=true.

  多对一和一对一索策略一般?lt; many-to-one>?lt; one-to-one>配置?lt; many-to-one>中需要配|的属性是 outer-joinQ同时还需要配|one端关联的< class>的lazy属性(配置的可不是< many-to-one>中的lazy哦)Q它们的l合后的索策略如下:

  1Q?outer-join=autoQ这是默认|如果lazy=true为gq检索,如果lazy=false切左外连接检索?/p>

  2Q?outer-join=trueQ无关于lazyQ都切左外连接检索?/p>

  3Q?outer-join=falseQ如果lazy=true为gq检索,否则为立x索?/p>

  可以看到Q在默认的情况下Qouter-join=autoQlazy=falseQ,对关联的one端对象Hibernate采用的迫切左外连接检索。依我看Q很多情况下Q我们ƈ不需要加载one端关联的对象Q很可能我们需要的仅仅是关联对象的idQ;另外Q如果关联对象也采用了迫切左外连接检索,׃出现select语句中有多个外连接表Q如果个数多的话会媄响检索性能Q这也是Z么Hibernate通过 hibernate.max_fetch_depth属性来控制外连接的深度。对于迫切左外连接检索,query的集合检索ƈ不适用Q它会采用立x索策略?/p>

  对于索策略,需要根据实际情况进行选择。对于立x索和延迟索,它们的优点在于select语句单(每张表一条语句)、查询速度快,~点在于兌表时需要多条select语句Q增加了讉K数据?/a>的频率。因此在选择x索和延迟索时Q可以考虑使用扚w索策略来减少select语句的数量(配置batch-size属性)。对于切左外q接索,优点在于select较少Q但~点是select语句的复杂度提高Q多表之间的兌会是很耗时的操作。另外,配置文g是死的,?nobr oncontextmenu="return false;" onmousemove="kwM(2);" id="key2" onmouseover="kwE(event,2, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">E序是活的,可以Ҏ需要在E序里显C的指定索策略(可能l常需要在E序中显C指定迫切左外连接检索)。ؓ了清楚检索策略的配置效果如何Q可以配|show_sql属性查看程序运行时Hibernate执行的sql语句?/p>



苏醄 2007-11-20 15:59 发表评论
]]>使用struts+spring+hibernate l装web应用http://www.tkk7.com/sutao/articles/161874.html苏醄苏醄Tue, 20 Nov 2007 07:50:00 GMThttp://www.tkk7.com/sutao/articles/161874.htmlhttp://www.tkk7.com/sutao/comments/161874.htmlhttp://www.tkk7.com/sutao/articles/161874.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/161874.htmlhttp://www.tkk7.com/sutao/services/trackbacks/161874.html使用struts+spring+hibernate l装web应用

来源Q?nbsp;作者:佚名 2007-11-02 出处Q?a target="_blank">pcdog.com

 

    其实Q就用Java建造一个不是很烦琐的web应用Q也不是件轻杄事情?在构架的一开始就有很多事情要考虑?从高处看Q摆?nobr oncontextmenu="return false;" onmousemove="kwM(2);" id="key2" onmouseover="kwE(event,2, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">开?/nobr>者面前有很多问题Q要考虑是怎样建立用户接口Q在哪里处理业务逻辑Q?怎样持久化的数据?/p>

  而这三层构架中,每一层都有他们要仔细考虑的?各个层该使用什么技术? 怎样的设计能松散耦合q能灉|改变Q?怎样替换某个层而不影响整体构架Q应?nobr oncontextmenu="return false;" onmousemove="kwM(5);" id="key3" onmouseover="kwE(event,5, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">E序如何做各U别的业务处理Q比如事务处理)Q?

    构架一个Web应用需要弄明白好多问题?q运的是Q已l有不少开发者已l遇到过q类问题Qƈ且徏立了处理q类问题的框架?一个好框架具备以下几点Q减d发者处理复杂的问题的负担(“不重复发明轮?#8221;Q; 内部有良好的扩展Q?q且有一个支持它的强大的用户团体。好的构架一般有针对性的处理某一c问题,q且能将它做好(Do One Thing wellQ。然而,你的E序中有几个层可能需要用特定的框架Q已l完成的UI(用户接口) q不代表你也可以把你的业务逻辑和持久逻辑偶合C的UI部分。D个例子, 你不该在一个Controller(控制?里面写JDBC代码作ؓ你的业务逻辑Q?q不是控制器应该提供的?一个UI 控制器应该委z其它l在UI范围之外的轻量lg?好的框架应该能指g码如何分布?更重要的是,框架能把开发者从~码中解攑և来,使他们能专心?nobr oncontextmenu="return false;" onmousemove="kwM(6);" id="key4" onmouseover="kwE(event,6, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">应用E序的逻辑Q这对客h说很重要Q?

    q篇文章讨论怎样l合几种着名的框架来得你的应用程序做到松弛耦合?

    如何建立你的架构Qƈ且怎样让你的各个应用层保持一致。?如何整合框架以便让每个层在以一U松散偶合的方式彼此作用而不用管低层的技术细节?q对我们来说真是一U挑战?q里讨论一个整合框架的{略( 使用3 U受Ƣ迎的开源框? Q表C层我们用StrutsQ?业务层我们用SpringQ而持久层则用Hibernate?你也可以用其他FrameWork替换只要能得到同L效果?见图1 Q框架组合示意图Q?

使用struts+spring+hibernate l装web应用Q图一Q? src=


应用E序的分?

    大部分的Web应用在职责上臛_能被分成4层。这四层是:presentationQ描qͼQpersistenceQ持久)QbusinessQ业务)和domain modelQ域模块Q。每个层在处理程序上都应该有一Ҏ的责Q, 而不应该在功能上与其它层混合Qƈ且每个层要与其它层分开的,但要l他们之间放一个通信接口。我们就从介l各个层开始,讨论一下这些层应该提供什么,不应该提供什么?

表示?The Presentation Layer)

    一般来Ԍ一个典型的Web应用的的末端应该是表C层?很多Java发者也理解Struts所提供的?象业务逻辑之类的被打包到org.apache.struts.Action.Q?因此Q我们很赞成使用Strutsq样的框架?

下面是Struts所负责的:

* 理用户的请?做出相应的响应?

* 提供一个Controller ,委派调用业务逻辑和其它上层处理?

* 处理异常Q抛lStruts Action

* 为显C提供一个模?

* UI验证?

以下条款Q不该在Struts昄层的~码中经常出现?它们与显C层无关的?

* 直接的与数据?/a>通信Q例如JDBC调用?

* 与你应用E序相关联的业务逻辑以及校验?

* 事物理?

在表C层引入q些代码Q则会带来高偶合和麻烦的l护?

持久?The Persistence Layer)

    典型的Web应用的另一个末端是持久层。这里通常是程序最Ҏ失控的地斏V开发者L低估构徏他们自己的持久框架的挑战性?a target="_blank">pȝ
内部的持l层不但需要大量调试时_而且q经常缺功能之变得难以控Ӟq是持久层的通病。还好有几个ORM开源框架很好的解决了这c问题。尤其是Hibernate?Hibernate为java提供了OR持久化机制和查询服务, 它还l已l熟悉SQL和JDBC API 的Java开发者一个学习桥梁,他们学习h很方ѝ?Hibernate的持久对象是ZPOJO和Java collections。此外,使用Hibernateq不妨碍你正在用的IDE?

L下面的条目,你在持久层编码中需要了解的?

* 查询对象的相?nobr oncontextmenu="return false;" onmousemove="kwM(1);" id="key1" onmouseover="kwE(event,1, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">信息的语句?Hibernate通过一个OO查询语言QHQLQ或者正则表辄API来完成查询?HQL非常cM于SQL-- 只是把SQL里的table和columns用Object和它的fields代替?你需要学习一些新的HQL语言Q不怎样Q他们容易理解而文档也做的很好?HQL是一U对象查询的自然语言Q花很小的代价就能学习它?

* 如何存储Q更斎ͼ删除数据库记录?

* 象Hibernateq类的高UORM框架支持大部分主数据库Qƈ且他们支?Parent/child关系Q事物处理,l承和多态?br />

业务层(The Business LayerQ?nbsp;

   一个典型Web应用的中间部分是业务层或者服务层?从编码的视角来看Q这层是最Ҏ被忽视的一层?而我们却往往在UI层或持久层周围看到这些业务处理的代码Q这其实是不正确的,因ؓ它导致了E序代码的紧密偶合,q样一来,随着旉推移q些代码很难l护。幸好,针对q一问题有好几种Frameworks存在?最受欢q的两个框架?a target="_blank">Spring和PicoContainer。这些ؓ也被UCؓmicrocontainersQ他们能让你很好的把对象搭配h?q两个框枉着手于‘依赖注射’(dependency injection)(q有我们知道?#8216;控制反{’Inversion of Control=IoC)q样的简单概c这文章将x于Spring的注(译注Q通过一个给定参数的SetterҎ来构造Bean,有所不同于FactoryQ? Springq提供了Setter Injection(type2)QConstructor Injection(type3){方式供我们选择?Spring把程序中所涉及到包含业务逻辑和Dao的Objects——例如transaction management handlerQ事物管理控Ӟ、Object Factoris(对象工厂)、service objectsQ服务组Ӟ——都通过XML来配|联pv来?

后面我们会D个例子来揭示一下Spring 是怎样q用q些概念?

业务层所负责的如下:

* 处理应用E序?业务逻辑和业务校?

* 理事物

* 允许与其它层怺作用的接?

* 理业务层别的对象的依赖?

* 在显C层和持久层之间增加了一个灵zȝ机制Q得他们不直接的联pd一赗?

* 通过揭示 从显C层C务层之间的Context来得到business services?

* 理E序的执行(从业务层到持久层Q?

域模块层QThe Domain Model Layer Q?
    既然我们致力于的是一个不是很复杂的Web的应用, 我们需要一个对象集合,让它在不同层之间Ud的?域模块层由实际需求中的业务对象组?比如, OrderLineItem , Product{等?开?/nobr>者在q层 不用那些DTOsQ仅xdomain object卛_?例如Q?a target="_blank">Hibernate允许你将数据?/a>中的信息存放入对象(domain objectsQ,q样你可以在q接断开的情况下把这些数据显C到UI层?而那些对象也可以q回l持l层Q从而在数据库里更新?而且Q你不必把对象{化成DTOsQ这可能似的它在不同层之间的在传输过E中丢失Q,q个模型使得Java开发者能很自然运用OOQ而不需要附加的~码?

一个简单例?

既然我们已经从全局上理解这些组件?现在p我们开始实践吧?我们q是?StrutsQSpring 和Hibernate。这三个框架已经被描q够多了Q这里就不重复介l了?q篇文章举例指导你如何用这三个框架整合开? q向你揭CZ个请求是如何贯穿于各个层的。(从用L加入一个Order到数据库Q显C;q而更新、删除)?

    既然每个层是互相作用的,我们先来创建domain objects。首先,我们要在q些Object中要定那些是需要持久化的,哪些是提供给business logicQ那些是昄接口的设计。下一步,我们配|我们的持久层ƈ且定义好Hibernate的OR mappings。然后定义好Business Objects。有了这些组成部分之后,我们?使用Spring把这些连接v来。最后,我们提供lSpring一个持久层Q从q个持久层里我们可以知道它是如何与业务逻辑层(business service layerQ通信的,以及它是怎样处理其他层抛出的异常的。?

域对象层QDomain Object LayerQ?

q层是编码的着手点Q我们的~码׃q层开始?例子中Order 与OrderItem 是一个One—To—Many的关pR?下面是Domain Object Layer的两个对象:

· com.meagle.bo.Order.java: 包含了一个Order的概要信?

· com.meagle.bo.OrderLineItem.java: 包含了Order的详l信?

    好好考虑怎你的package命名,q反应出了你是怎样分层的?例如 domain objects在程序中可能打包在com.meagle.bo内?更详l一点将打包在com. meagle.bo的子目录下面。business logic应该从com.meagle.serice开始打包,而DAO 对象应该位于com.meagle.service.dao.hibernate。反应Forms和Actions的持久对象(presentation classesQ?应该分别攑֜ com.meagle.action和com.meagle.forms包。准的l包命名使得你的classes很好分割q且易于l护Qƈ且在你添加新的classesӞ能得程序结构上保持上下一致?

持久层的配置QPersistence Layer ConfigurationQ?

    建立Hibernate的持久层 需要好几个步骤?W一步让我们把BO持久化?既然Hibernate是通过POJO工作的, 因此Order?OrderLineItem对象需要给所有的fileds 加上getter,setterҎ?Hibernate通过XML文g来映?OR)对象Q以下两个xml文g分别映射了Order 和OrderItem对象。(q里有个叫XDoclet工具可以自动生成你的XML影射文gQ?

- Order.hbm.xml
- OrderLineItem.hbm.xml

    你可以在WebContent/WEB-INF/classes/com/meagle/bo目录下找到这些xml文g。Hibernate?[urlhttp://www.hibernate.org/hib_docs/api/net/sf/hibernate/SessionFactory.html]SessionFactory [/url]是用来告诉程?应该与哪个数据库通信Q该使用哪个q接池或使用了DataSourceQ应该加载哪些持久对象。而Session接口是用来完成SelectingQSavingQDelete和Updatingq些操作。后面的我们讲qSessionFactory和Session是怎样讄的?

业务层的配置QBusiness Layer ConfigurationQ?

    既然我们已经有了domain objectsQ接下来我们pbusiness service objects了,用他们来执行E序的logic,调用持久层,得到UI层的requests,处理transactionsQƈ且控?exceptions?Z这些连接v来ƈ且易于管理,我们用面向方面的 SpringFramework?Spring 提供了控制倒置Qinversion of control 0==IoC)和注依赖设|(setter dependency injectionQ这些方式(可供选择Q,用XML文g对象连接v来?IoC是一个简单概念(它允怸个对象在上层接受其他对象的创建)Q用IoCq种方式让你的对象从创徏中释放了出来Q降低了偶合度?

    q里是一个没有用IoC的对象创建的例子Q它有很高偶合度?

使用struts+spring+hibernate l装web应用Q图二)


?2.没有使用 IoC. A 创徏?B ?C

    而这里是一个用IoC的例子,q种方式允许对象在高层可以创建ƈq入另外一个对象,所以这样可以直接被执行?

使用struts+spring+hibernate l装web应用Q图三)


?3. 对象使用?IoC?A 包含了接受B,C?setterҎ , q同栯C 由A创徏B,C的目的?

建立我们的业务服务对象(Building Our Business Service ObjectsQ?

    Business Object中的SetterҎ接受的是接口Q这h们可以很松散的定义对象实玎ͼ然后注入。在我们的案例中Q我们将用一个business service object接收一个DAO,用它来控制domain objects的持久化。由于在q个例子中用了HibernateQ我们可以很方便的用其他持久框架实现 同时通知Spring 有新的DAO可以使用了?

    在面向接口的~程中,你会明白 “注射依赖”模式是怎样松散耦合你的业务逻辑和持久机制的Q)?br />

使用struts+spring+hibernate l装web应用Q图四)


?4. Spring是q样Z配置文gQ将各个Bean搭徏在一赗?

q个例子使用一?TransactionProxyFactoryBeanQ它定义了一个setTransactionManager()。这对象很有用,他能很方便的处理你申明的事物q有Service Object。你可以通过transactionAttributes属性来定义怎样处理。想知道更多q是参考TransactionAttributeEditor吧?

TransactionProxyFactoryBean q有个setter. q会被我?Business service objectQorderTargetQ引用, orderTarget定义了业务服务层Qƈ且它q有个属性,由setOrderDAO()引用。这个属?nbsp;

    Spring 和Bean 的还有一点要注意的: bean可以以用两种方式创造?q些都在单例模式QSingtonQ和原型模式QpropotypeQ中定义了。默认的方式是singleton,q意味着׃n的实例将被束~。而原形模式是在Spring用到bean的时候允许新建实例的。当每个用户需要得C们自己Bean的CopyӞ你应该仅使用prototype模式。(更多的请参考设计模式中的单例模式和原Ş模式Q?

提供一个服务定位器QProviding a Service LocatorQ?

    既然我们已经我们的Serices和DAO搭配h了。我们需要把我们的Service昄到其他层?q个通常是在Struts或?a target="_blank">Swingq层?nobr oncontextmenu="return false;" onmousemove="kwM(2);" id="key0" onmouseover="kwE(event,2, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">~码。一个简单方法就是用 服务定位器返回给Spring context 。当Ӟ可以通过直接调用Spring中的Bean来做?

下面是一个Struts Actin 中的服务定位器的一个例子?
代码:

public abstract class BaseAction extends Action {
 
  private IOrderService orderService;
 
  public void setServlet(ActionServlet
                                 actionServlet) {
    super.setServlet(actionServlet);
    ServletContext servletContext =
               actionServlet.getServletContext();
 
    WebApplicationContext wac =
      WebApplicationContextUtils.
         getRequiredWebApplicationContext(
                                 servletContext);
 
      this.orderService = (IOrderService)
                     wac.getBean("orderService");
  }
 
  protected IOrderService getOrderService() {
    return orderService;
  }
}

UI 层配|?QUI Layer ConfigurationQ?

    q个例子里UI?使用了Struts framework. q里我们要讲qC下在l程序分层的时候, 哪些是和Struts部分的。我们就从一个Struts-config.xml文g中的Action的配|?nobr oncontextmenu="return false;" onmousemove="kwM(1);" id="key1" onmouseover="kwE(event,1, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">信息开始吧?
代码:

struts-config.xml file.

<action path="/SaveNewOrder"
    type="com.meagle.action.SaveOrderAction"
    name="OrderForm"
    scope="request"
    validate="true"
    input="/NewOrder.jsp">
  <display-name>Save New Order</display-name>
  <exception key="error.order.save"
    path="/NewOrder.jsp"
    scope="request"
    type="com.meagle.exception.OrderException"/>
  <exception key="error.order.not.enough.money"
    path="/NewOrder.jsp"
    scope="request"
    type="com.
          meagle.
          exception.
          OrderMinimumAmountException"/>
  <forward name="success" path="/ViewOrder.jsp"/>
  <forward name="failure" path="/NewOrder.jsp"/>
</action>

    SaveNewOrder q个Action是用来持久化UI层里的表单提交过来Order的。这是Struts中一个很典型的Action; 注意观察q个Action中exception配置Q这些Exceptions也在Spring 配置文g(applicationContext-hibernate.xml)中配|了Q就?business service object 的transactionAttributes属性里Q?当异常在业务层被被抛出时Q我们可以控制他们,q当的显C给UI层?

    W一个异常,OrderException,在持久层保存order对象p|的时候被触发。这导致事物回滚ƈ且通过BO把异常回传到Strutsq一层?

W二个异常,OrderMinimumAmountException也同W一个一栗?

    搭配整和的最后一?通过是让你显C层和业务层相结合。这个已l被服务定位器(service locatorQ实CQ前面讨了)Q?q里服务层作Z个接口提供给我们的业务逻辑和持久层?

    SaveNewOrder Action 在Struts中用一个服务定位器Qservice locatorQ来调用执行业务Ҏ的?Ҏ代码如下Q?

代码:
public ActionForward execute(

  ActionMapping mapping,

  ActionForm form,

  javax.servlet.http.HttpServletRequest request,

  javax.servlet.http.HttpServletResponse response)

  throws java.lang.Exception {

 

  OrderForm oForm = (OrderForm) form;

 

  // Use the form to build an Order object that

  // can be saved in the persistence layer.

  // See the full source code in the sample app.

 

  // Obtain the wired business service object

  // from the service locator configuration

  // in BaseAction.

  // Delegate the save to the service layer and

  // further upstream to save the Order object.

  getOrderService().saveNewOrder(order);

 

  oForm.setOrder(order);

 

  ActionMessages messages = new ActionMessages();

  messages.add(

      ActionMessages.GLOBAL_MESSAGE,

            new ActionMessage(

      "message.order.saved.successfully"));

 

  saveMessages(request, messages);

 

  return mapping.findForward("success");

}


ȝ

    文章在技术和构架斚w掩盖了很多低层的基础信息Q?文章的主要的意图在于让你意识到如何给?nobr oncontextmenu="return false;" onmousemove="kwM(4);" id="key3" onmouseover="kwE(event,4, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">应用E序分层?分层可以“解?#8221;你的代码——允许新的组件被dq来Q而且让你的代码易于维护?q里用到的技术只是专注于?#8220;解偶”做好。不怎样Q用这L构架可以让你用其他技术代替现在的层。例如,你可能不使用Hibernate实现持久化。既然你在DAO中面向接口的~程的,所以你完全可以用iBATIS来代ѝ或者,你也可能想用 Struts外的其他的技术或者框架替换现在的UI层(转换久层Q实现层q不应该直接影响C的业务逻辑和业务服务层Q。用适当的框架搭Z的Web应用Q其实也不是一件烦琐的工作Q更主要的是?#8220;解?#8221;了你E序中的各个层?

后记Q?

    q篇文章后,只是觉得?nobr oncontextmenu="return false;" onmousemove="kwM(5);" id="key4" onmouseover="kwE(event,5, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">喜欢Q于是就译了,当然同时也准备着挨大家扔来的鸡蛋Q)?

    文章里ƈ没有太多的技术细节,和详l的步骤。如果你从未使用q这些框架而在q行实例E序遇上困难的话Q可以到CSDN论坛Java Open Source版发_我一定会详细解答的(啊哦Q这不算做广告吧Q)Q?

    文章是从一个构架的角度讲述了如何搭配现有的开源框架进行分层, 有太多的术语我都不知道怎么表达Q而且可能有很多语句存在错误。如果媄响了你的阅读Q请你直接点原文地址Q我同时也象你说声抱歉?br />


苏醄 2007-11-20 15:50 发表评论
]]>
hibernate延迟加蝲http://www.tkk7.com/sutao/articles/158759.html苏醄苏醄Wed, 07 Nov 2007 03:02:00 GMThttp://www.tkk7.com/sutao/articles/158759.htmlhttp://www.tkk7.com/sutao/comments/158759.htmlhttp://www.tkk7.com/sutao/articles/158759.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/158759.htmlhttp://www.tkk7.com/sutao/services/trackbacks/158759.html其实q个异常写的非常之清楚,是会话关闭Q无法对Hibernate实体q行操作。造成q样的情冉|很多Q什么书写错误啊Q逻辑错误啊?/p>

但就此说一下关于lazy机制Q?/p>

延迟初始化错误是q用Hibernate开发项目时最常见的错误。如果对一个类或者集合配|了延迟索策略,那么必须当代理类实例或代理集合处于持久化状态(卛_?/span>Session范围内)Ӟ才能初始化它。如果在游离状态时才初始化它,׃产生延迟初始化错误?span>

下面把Customer.hbm.xml文g?lt;class>元素的lazy属性设为trueQ表CZ用gq检索策略:

<class name="mypack.Customer" table="CUSTOMERS" lazy="true">

当执?/span>Session的load()ҎӞHibernate不会立即执行查询CUSTOMERS表的select语句Q仅仅返回Customercȝ代理cȝ实例Q这个代理类L以下特征Q?span>

Q?Q?由Hibernate在运行时动态生成,它扩展了Customerc,因此它承了Customercȝ所有属性和ҎQ但它的实现对于应用E序是透明的?span>
Q?Q?当Hibernate创徏Customer代理cd例时Q仅仅初始化了它的OID属性,其他属性都为nullQ因此这个代理类实例占用的内存很?span>
Q?Q当应用E序W一ơ访问Customer代理cd例时Q例如调用customer.getXXX()或customer.setXXX()ҎQ, Hibernate会初始化代理cd例,在初始化q程中执行select语句Q真正从数据库中加蝲Customer对象的所有数据。但有个例外Q那是?应用E序讉KCustomer代理cd例的getId()ҎӞHibernate不会初始化代理类实例Q因为在创徏代理cd例时OID存在了Q不?到数据库中去查询?span>

提示QHibernate采用CGLIB工具来生成持久化cȝ代理cRCGLIB是一个功能强大的Java字节码生成工P它能够在E序q行时动态生成扩 ?JavacL者实现Java接口的代理类。关于CGLIB的更多知识,请参考:http://cglib.sourceforge.net/?span>

以下代码先通过Session的load()Ҏ加蝲Customer对象Q然后访问它的name属性:

tx =
session.beginTransaction();
Customer customer=(Customer)
session.load(Customer.class,new Long(1));
customer.getName();
tx.commit();

在运?/span>session.load ()Ҏ时Hibernate不执行Q何select语句Q仅仅返回Customercȝ代理cȝ实例Q它的OID?Q这是由load()Ҏ的第二个 参数指定的。当应用E序调用customer.getName()ҎӞHibernate会初始化Customer代理cd例,从数据库中加?Customer对象的数据,执行以下select语句Q?span>

select * from CUSTOMERS where ID=1;
select * from ORDERS where CUSTOMER_ID=1;

?lt;class>元素的lazy属性ؓtrueQ会影响
Session的load()Ҏ的各U运行时行ؓQ下面D例说明?span>

1
Q如果加载的Customer对象在数据库中不存在Q?/span>Session的load()Ҏ不会抛出异常Q只有当q行customer.getName()Ҏ时才会抛Z下异常:

ERROR LazyInitializer:63
- Exception initializing proxy
net.sf.hibernate.ObjectNotFoundException: No row with the given identifier exists: 1, of class:
mypack.Customer

2
Q如果在整个Session范围内,应用E序没有讉KqCustomer对象Q那么Customer代理cȝ实例一直不会被初始化,Hibernate不会执行Mselect语句。以下代码试囑֜关闭Session后访问Customer游离对象Q?span>

tx =
session.beginTransaction();
Customer customer=(Customer)
session.load(Customer.class,new Long(1));
tx.commit();
session.close();
customer.getName();

׃引用变量customer引用的Customer代理cȝ实例?/span>Session范围内始l没有被初始化,因此在执行customer.getName()ҎӞHibernate会抛Z下异常:

ERROR LazyInitializer:63
- Exception initializing proxy
net.sf.hibernate.HibernateException: Couldnotinitializeproxy-theowningSessionwasclosed

由此可见QCustomer代理cȝ实例只有在当?/span>Session范围内才能被初始化?span>

3
Qnet.sf.hibernate.Hibernatecȝ
initialize()静态方法用于在Session范围内显式初始化代理cd例,isInitialized()Ҏ用于判断代理cd例是否已l被初始化。例如:

tx =
session.beginTransaction();
Customer customer=(Customer)
session.load(Customer.class,new Long(1));
if(!Hibernate.isInitialized(customer))
Hibernate.
initialize(customer);
tx.commit();
session.close();
customer.getName();

以上代码?/span>Session范围内通过Hibernatecȝinitialize()Ҏ昑ּ初始化了Customer代理cd例,因此?/span>Session关闭后,可以正常讉KCustomer游离对象?span>

4
Q当应用E序讉K代理cd例的getId()ҎӞ不会触发Hibernate初始化代理类实例的行为,例如Q?span>

tx =
session.beginTransaction();
Customer customer=(Customer)
session.load(Customer.class,new Long(1));
customer.getId();
tx.commit();
session.close();
customer.getName();

当应用程序访问customer.getId()ҎӞ该方法直接返回Customer代理cd例的OID|无需查询数据库。由于引用变?customer始终引用的是没有被初始化的Customer代理cd例,因此?/span>Session关闭后再执行customer.getName()ҎQ?Hibernate会抛Z下异常:

ERROR LazyInitializer:63 - Exception initializing proxy
net.sf.hibernate.HibernateException: Couldnotinitializeproxy-theowningSessionwasclosed

解决ҎQ?/span>

׃hibernate采用了lazy=true,q样当你用hibernate查询?q回实际为利用cglib增强的代理类,但其q没有实际填 ?当你在前?利用它来取?getXXX)?q时Hibernate才会到数据库执行查询,q填充对?但此时如果和q个代理cȝ关的session已关闭掉,׃产生U错?span>.
在做一对多Ӟ有时会出?could not initialize proxy - clothe owning Session was sed,q个好像是hibernate的缓存问?问题解决:需要在<many-to-one>里设|lazy="false". 但有可能会引发另一个异常叫

failed to lazily initialize a collection of role: XXXXXXXX, no session or session was closed

此异常解x案请察看本h博客Q?a >http://hi.baidu.com/kekemao1Q的Hibernate异常中的《failed to lazily initialize a collection of role异常?span>

?
解决Ҏ:在web.xml中加?span>
<filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>
     org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    </filter-class>
</filter
<filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>*.do</url-pattern>
</filter-mapping>
可以了;

参考了:
Hibernate
与gq加载:

Hibernate对象关系映射提供延迟的与非gq的对象初始化。非延迟加蝲在读取一个对象的时候会与q个对象所有相关的其他对象一赯取出来? q有时会D成百的(如果不是成千的话Qselect语句在读取对象的时候执行。这个问题有时出现在使用双向关系的时候,l常会导致整个数据库都在初始? 的阶D被d来了。当Ӟ你可以不厌其烦地查每一个对象与其他对象的关p,q把那些最昂贵的删除,但是到最后,我们可能会因此失M本想在ORM工具?获得的便利?/p>


一个明昄解决Ҏ是用Hibernate提供的gq加载机制。这U初始化{略只在一个对象调用它的一对多或多对多关系时才关pd象读取出来。这个过 E对开发者来说是透明的,而且只进行了很少的数据库操作hQ因此会得到比较明显的性能提升。这Ҏ术的一个缺h延迟加蝲技术要求一?Hibernate会话要在对象使用的时候一直开着。这会成为通过使用DAO模式持久层抽象出来时的一个主要问题。ؓ了将持久化机制完全地抽象出来Q所 有的数据库逻辑Q包括打开或关闭会话,都不能在应用层出现。最常见的是Q一些实C单接口的DAO实现cd数据库逻辑完全装h了。一U快速但是笨? 的解x法是攑ּDAO模式Q将数据库连接逻辑加到应用层中来。这可能对一些小的应用程序有效,但是在大的系l中Q这是一个严重的设计~陷Q妨了pȝ? 可扩展性?/p>

在Web层进行gq加?/p>

q运的是QSpring框架为Hibernate延迟加蝲与DAO模式的整合提供了一U方便的解决Ҏ。对那些不熟悉Spring?Hibernate集成使用的hQ我不会在这里讨多的l节Q但是我你去了解Hibernate与Spring集成的数据访问。以一个Web应用?例,Spring提供了OpenSessionInViewFilter和OpenSessionInViewInterceptor。我们可以随意选择 一个类来实现相同的功能。两U方法唯一的不同就在于interceptor在Spring容器中运行ƈ被配|在web应用的上下文中,而Filter?span> Spring之前q行q被配置在web.xml中。不用哪个Q他们都在请求将当前会话与当前(数据库)U程l定时打开Hibernate会话。一旦已l?定到U程Q这个打开了的Hibernate会话可以在DAO实现cM透明C用。这个会话会为gq加载数据库中值对象的视图保持打开状态。一旦这个逻辑?囑֮成了QHibernate会话会在Filter的doFilterҎ或者Interceptor的postHandleҎ中被关闭。下面是每个l?件的配置CZQ?/p>


Interceptor
的配|?

<beans>
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="openSessionInViewInterceptor"/>
</list>
</property>
<property name="mappings">

</bean>

<bean name="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
</beans>

Filter的配|?/p>

<web-app>

<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
</filter-class>
</filter>

<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*. spring </url-pattern>
</filter-mapping>

</web-app>


实现Hibernate的Dao接口来用打开的会话是很容易的。事实上Q如果你已经使用了Spring框架来实C的Hibernate Dao,很可能你不需要改变Q何东ѝ方便的HibernateTemplate公用lg使访问数据库变成菜一,而DAO接口只有通过q个lg才可? 讉K到数据库。下面是一个示例的DAOQ?/p>


public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO {

public Product getProduct(Integer productId) {
return (Product)getHibernateTemplate().load(Product.class, productId);
}

public Integer saveProduct(Product product) {
return (Integer) getHibernateTemplate().save(product);
}

public void updateProduct(Product product) {
getHibernateTemplate().update(product);
}
}

在业务逻辑层中使用延迟加蝲

即在视囑֤面,Spring框架也通过使用AOP 拦截?HibernateInterceptor来得gq加载变得很Ҏ实现。这?span>Hibernate 拦截器透明地将调用配置在Spring应用E序上下文中的业务对象中Ҏ的请求拦截下来,在调用方法之前打开一个Hibernate会话Q然后在Ҏ执行 完之后将会话关闭。让我们来看一个简单的例子Q假设我们有一个接口BussinessObjectQ?/p>


public     interface    BusinessObject     {
public     void    doSomethingThatInvolvesDaos();
}
cBusinessObjectImpl实现了BusinessObject接口:

public     class    BusinessObjectImpl    implements    BusinessObject     {
public     void    doSomethingThatInvolvesDaos()     {
//    lots of logic that calls
//    DAO classes Which access
//    data objects lazily  
}  
}  


通过在Spring应用E序上下文中的一些配|,我们可以让将调用BusinessObject的方法拦截下来,再o它的Ҏ支持延迟加蝲。看看下面的一个程序片D:


<beans>
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="businessObjectTarget" class="com.acompany.BusinessObjectImpl">
<property name="someDAO"><ref bean="someDAO"/></property>
</bean>
<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"><ref bean="businessObjectTarget"/></property>
<property name="proxyInterfaces">
<value>com.acompany.BusinessObject</value>
</property>
<property name="interceptorNames">
<list>
<value>hibernateInterceptor</value>
</list>
</property>
</bean>
</beans>

当businessObject被调用的时候,HibernateInterceptor打开一个Hibernate会话Qƈ调用请求传递给 BusinessObjectImpl对象。当BusinessObjectImpl执行完成后,HibernateInterceptor透明地关闭了 会话。应用层的代码不用了解Q何持久层逻辑Q还是实C延迟加蝲?/p>


在单元测试中试延迟加蝲

最后,我们需要用J-Unit来测试我们的延迟加蝲E序。我们可以轻易地通过重写TestCasecM的setUp和tearDownҎ来实现这个要求。我比较喜欢用这个方便的抽象cM为我所有测试类的基cR?/p>


public abstract class MyLazyTestCase extends TestCase {

private SessionFactory sessionFactory;
private Session session;

public void setUp() throws Exception {
super.setUp();
SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory");
session = SessionFactoryUtils.getSession(sessionFactory, true);
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));

}

protected Object getBean(String beanName) {
//Code to get objects from Spring application context
}

public void tearDown() throws Exception {
super.tearDown();
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);
}
}



苏醄 2007-11-07 11:02 发表评论
]]>
对session对象在web开发中的创Z及sessionId生成q返回客L的运行机?http://www.tkk7.com/sutao/articles/158756.html苏醄苏醄Wed, 07 Nov 2007 02:54:00 GMThttp://www.tkk7.com/sutao/articles/158756.htmlhttp://www.tkk7.com/sutao/comments/158756.htmlhttp://www.tkk7.com/sutao/articles/158756.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/158756.htmlhttp://www.tkk7.com/sutao/services/trackbacks/158756.html
session对象当客L首次讉K?创徏一个新的session对象.q同时生成一个sessionId,q在此次响应中将sessionId以响应报文的方式些回客户端浏览器内存或以重写url方式送回客户?来保持整个会?只要sever端的q个session对象没有销?以后再调用request.getSession() 时就直接Ҏ客户端的sessionId来检索server端生成的session对象q返?不会再次L?除非Ҏ此sessionId没有索到 session对象.

下面是在IE下测?因ؓIE6.0的一个BUG是IE的隐U设|即使是L所有cookie?也还是会以会话cookie来保存sessionId.所以下面都是以会话cookie来讨论的,

(1)在server没有关闭,q在session对象销毁时间内,当客L再次来请求server端的servlet或jsp? 会在W一ơ请求时生成的sessionIdq带在h信息头中q向server端发?server端收到sessionId后根据此 sessionId会去搜烦(此过E是透明?server对应的session对象q直接返回这个session对象,此时不会重新d立一个新?session对象.

(2)当server关闭(之前产生的session对象也就消亡?,或session对象q了光毁时间后, 览器窗口不?q在本浏览器H口再次去请求sever端的servlet和jsp?此时同样会将sessionId(server关闭?session销毁时生成的sessionId)发送到server?serverҎsessionIdL其对应的session对象,但此?session对象已经不存?此时会重新生成一个新的session对象,q生成新的sessionIdq同样将q个新生成的sessionId以响应报文的形式送到览器内存中.

(3)当server没有关闭,qsession对象在其销毁时间内,当请求一个jsp面回客L? 关闭此浏览器H口,此时其内存中的sessionId也就随之销?在重新去hsever端的servlet或jsp?会重新生成一?sessionIdl客L览?q存在浏览内存中.

上面的理论在servlet中测试都是成立的,下面谈一下在struts框架下进行上面的试时的不同的地?

先简要说下测试程序的程:

客户端请求index.do--->q入server端的IndexAction--->转向login.jsp面----->hlogin.do----->q入server端的LoginAction.

首先说明:IndexAction中没有去产生session对象,login.jsp中设|?

(1)环境servlet + jsp:

在sevlet+jsp试跟踪?在index.doq入IndexAction后{向login.jsp?此时览器内存中是没有会话cookie?那么在login.jsp上请求login.doq入LoginAction?用request.getCookies()试?其值是为null?l果是稳合的,因ؓ从始|终没有产生qsession?

(2)环境struts + jsp:

在struts+jsp试跟踪?跟上面的程一?开始想l果也应该是一L,但经q调试后发现l果却不是所想的那样.在login.doq入 LoginActoin后用,用request.getCookies()试?发现其g为null,卛_有name和value,开始很不理?因ؓҎ没有创session对象,哪来的会话cookie值呢.但是l果?那么想着此时览器内存中也就应该有会话cookie,问题在q里! 从哪里来?

后来l过仔细考虑?惛_struts中的特点,我们自己写的ActioncLl承struts的Action?而且之前是经qstruts的中央控制器ActionServlet来控制{向的,所以我惌定是在程序进入我自己写的IndexAction之前, struts框架中的代码肯定已经创徏了session对象q已l生成了sessionId.于是找到相关书c查看了ActionServlet工作程以及调用哪些c?看了之后果然在其中看CHttpSession session = request.getSession();q样一句话!于是{案也就明了?

大家知道struts的ActionServletcM在接收到我们客户端的h(*.do)?之前会做一pd初始化工?,q不是直接去处理我们的请求ƈ调用相应的Action(我们写的?IndexAction),而是处理工作交lRequestProcessorc?其processҎ中会调用一pd的方法来完成相应的请求处理和转向操作.其中有一个方法引起了我的x,是processLocale()Ҏ.



Struts框架:RequestProcesscM的processLocale()Ҏ原型如下:

E序代码:
protected void processLocale(HttpServletRequest request,
HttpServletResponse response) {
// Are we configured to select the Locale automatically?
if (!moduleConfig.getControllerConfig().getLocale()) {
return;
}
// Has a Locale already been selected?
HttpSession session = request.getSession();
if (session.getAttribute(Globals.LOCALE_KEY) != null) {
return;
}
// Use the Locale returned by the servlet container (if any)
Locale locale = request.getLocale();
if (locale != null) {
if (log.isDebugEnabled()) {
log.debug(" Setting user locale '" + locale + "'");
}
session.setAttribute(Globals.LOCALE_KEY, locale);
}
}

此类在struts-config.xml配置文g中有对应的配|项: < controller locale="true">< /controller> 其缺省状态locale属性的gؓtrue,也就会调用processLocaleҎ,q在W一ơ请求时创徏session对象和生?sessionId.但改为false?在第一ơ请求到达ActionServlet后不会调用processLocaleҎ,也就不会生成 session对象了?br />
l果也就出来了,在struts应用?*.do到达server端后l过ActionServlet后{x们自己写的IndexAction之前, < controller locale="true">< /controller>(~省状? ?已l生了session对象和sessionId,q是struts框架cM生成?即我们在IndexAction中写?HttpSession session = request.getSession();其也是RequestProcesscM的processLocale()Ҏ生成?此时其session 的isNew也还是true,因ؓq没有返回客L,其是新创建的,那么按照上面的流E?当在login.jsp上通过login.doq入 LoginAction?其request.getCookies()固然也就有g!q且其值是RequestProcesscM?processLocale()Ҏ产生session对象时生成的.

如果我们在struts-config.xml中加?lt; controller locale="false">< /controller> ?此时如果再根据上面的程来跟t程?q在LoginAction用request.getCookies()试?其值是为null?当然?IndexAction写上HttpSession session = request.getSession();时其是进入IndexAction时新创徏?isNew也是true?br />



察看了JBOSS的源代码Q命名服务器抛出的这个异常分析如?nbsp;  
  java.net.SocketException:   Software   caused   connection   abort:   socket   write   error   
  at   java.net.SocketOutputStream.socketWrite0(Native   Method)   
  at   java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)   
  at   java.net.SocketOutputStream.write(SocketOutputStream.java:136)   
  at   java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1639)   
  at   java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1548)   
  at   java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1146)   
  at   java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1100)   
  at   java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1241)   
  at   java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1052)   
  at   java.io.ObjectOutputStream.writeFatalException(ObjectOutputStream.java:1355)   
  at   java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:281)   
    
  上述异常是由于这L原因造成的:   
    
  1?客户端进行查找是NamingContext会徏立到命名服务器的Socketq接。(此连接是带读取超时的Q)   
  2?服务器接收了客户端的q接Q客户端可以l向下运行。于是客Lq行到ObjectInputStream的readObject处,q等待。此Ӟ客户端是惌得到NamingServer的stub?nbsp;  
  3?服务端由于线E繁忙,q迟不能客L需要的stub写入ObjectOutputStream。于是客L{待时Q然后客L抛出异常。如果此查找操作是在d操作Q客户在dp|后选择推出E序。则Socket被关闭?nbsp;  
  4?服务端闲下来后调用ObjectOutputStream的writeObjectҎQ此时由于客LSocket关闭Q最l抛Zq异常?nbsp;  
    
  q是我们公司的一个牛人分析的Q后来察看了JMS也存在类似问题。另QJBOSS的源代码质量不高QJNDI中存在socket未关闭的情况QJMS代码中socket用法也很不规范。大家小心了 




Hibernate构架应用中常用保存方式区?br /> TagQ数据库  pda  ie  hibernate  
下一?1 2

hibernate对于对象的保存提供了太多的方法,他们之间有很多不同,q里l说一下,以便区别Q?br />
一、预备知识:

在所有之前,说明一下,对于hibernateQ它的对象有三种状态,transient、persistent、detached

下边是常见的译办法Q?br />
transientQ瞬态或者自由?br />
persistentQ持久化状?br />
detachedQ脱状态或者游L?br />
q状态的实例可以通过调用saveQ)、persistQ)或者saveOrUpdateQ)Ҏq行持久化?br />
持久化实例可以通过调用 deleteQ)变成q状态。通过getQ)或loadQ)Ҏ得到的实例都是持久化状态的?br />
q状态的实例可以通过调用 updateQ)?saveOrUpdateQ)、lockQ)或者replicateQ)q行持久化?br />
saveQ)和persistQ)会引发SQL的INSERTQdeleteQ)会引发SQLDELETEQ而updateQ)或mergeQ)会引发SQLUPDATE.Ҏ久化QpersistentQ实例的修改在刷新提交的时候会被检到Q它也会引v SQLUPDATE.saveOrUpdateQ)或者replicateQ)会引发SQLINSERT或者UPDATE

二、save 和update区别

把这一Ҏ在第一位的原因是因一Ҏ最常用的?br />
save的作用是把一个新的对象保?br />
update是把一个脱状态的对象保存

三、update 和saveOrUpdate区别

q个是比较好理解的,֐思义QsaveOrUpdate基本上就是合成了save和update引用hibernate reference中的一D话来解释他们的使用场合和区别?br />
通常下面的场景会使用updateQ)或saveOrUpdateQ)Q?br />
E序在第一个session中加载对?br />
该对象被传递到表现?br />
对象发生了一些改?br />
该对象被q回C务逻辑?br />
E序调用W二个session的updateQ)Ҏ持久q些改动

saveOrUpdateQ)做下面的事:

如果对象已经在本session中持久化了,不做M?br />
如果另一个与本session兌的对象拥有相同的持久化标识(identifierQ,抛出一个异?br />
如果对象没有持久化标识(identifierQ属性,对其调用saveQ)

如果对象的持久标识(identifierQ表明其是一个新实例化的对象Q对其调用saveQ)

如果对象是附带版本信息的Q通过或) q且版本属性的D明其是一个新实例化的对象QsaveQ)它?br />
四、persist和save区别

q个是最qL的一对,表面上看h使用哪个都行Q在hibernate reference文档中也没有明确的区分他们?br />
q里l出一个明的区分。(可以跟进src看一下,虽然实现步骤cMQ但是还是有l微的差别)

1.persist把一个瞬态的实例持久化,但是q?不保?标识W被立刻填入到持久化实例中,标识W的填入可能被推q到flush的时间?br />
2.persist"保证"Q当它在一个transaction外部被调用的时候ƈ不触发一个Sql InsertQ这个功能是很有用的Q当我们通过l承Session/persistence context来封装一个长会话程的时候,一个persistq样的函数是需要的?br />
3.save"不保?W?条,它要q回标识W,所以它会立x行Sql insertQ不是不是在transaction内部?br />
五、saveOrUpdateCopyQmerge和update区别

首先说明merge是用来代替saveOrUpdateCopy?然后比较update和mergeQupdate的作用上边说了,q里说一下merge的作用?br />
如果session中存在相同持久化标识QidentifierQ的实例Q用用户l出的对象的状态覆盖旧有的持久实例

如果session没有相应的持久实例,则尝试从数据库中加蝲Q或创徏新的持久化实例,最后返回该持久实例

用户l出的这个对象没有被兌到session上,它依旧是q?br />
重点是最后一句:

当我们用update的时候,执行完成后,我们提供的对象A的状态变成持久化状?br />
但当我们使用merge的时候,执行完成Q我们提供的对象Aq是q状态,hibernate或者new了一个BQ或者检索到一个持久对象,q把我们提供的对象A的所有的值拷贝到q个BQ执行完成后B是持久状态,而我们提供的Aq是托管状态?br />
六、flush和update区别

q两个的区别好理?br />
update操作的是在脱状态的对象Q而flush是操作的在持久状态的对象?br />
默认情况下,一个持久状态的对象是不需要update的,只要你更改了对象的|{待hibernate flushp动保存到数据库了。hibernate flush发生再几U情况下Q?br />
1.调用某些查询的时?br />
2.transaction commit的时?br />
3.手动调用flush的时?br />
七、lock和update区别

update是把一个已l更改过的脱状态的对象变成持久状?br />
lock是把一个没有更改过的脱状态的对象变成持久状?br />
对应更改一个记录的内容Q两个的操作不同Q?br />
update的操作步骤是Q?br />
更改q的对?>调用update

lock的操作步骤是Q?br />
调用lock把对象从q状态变成持久状态—?gt;更改持久状态的对象的内容—?gt;{待flush或者手动flush




苏醄 2007-11-07 10:54 发表评论
]]>
proxy-lazy机制http://www.tkk7.com/sutao/articles/144546.html苏醄苏醄Wed, 12 Sep 2007 09:15:00 GMThttp://www.tkk7.com/sutao/articles/144546.htmlhttp://www.tkk7.com/sutao/comments/144546.htmlhttp://www.tkk7.com/sutao/articles/144546.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/144546.htmlhttp://www.tkk7.com/sutao/services/trackbacks/144546.htmlld not initialize proxy - the owning Session was closed (幅一)
2007-05-11 09:52

其实q个异常写的非常之清楚,是会话关闭Q无法对Hibernate实体q行操作。造成q样的情冉|很多Q什么书写错误啊Q逻辑错误啊?/p>

但就此说一下关于lazy机制Q?/p>

延迟初始化错误是q用Hibernate开发项目时最常见的错误。如果对一个类或者集合配|了延迟索策略,那么必须当代理类实例或代理集合处于持久化状态(卛_?/font>Session范围内)Ӟ才能初始化它。如果在游离状态时才初始化它,׃产生延迟初始化错误?br />
下面把Customer.hbm.xml文g?lt;class>元素的lazy属性设为trueQ表CZ用gq检索策略:

<class name="mypack.Customer" table="CUSTOMERS" lazy="true">

当执?/font>Session的load()ҎӞHibernate不会立即执行查询CUSTOMERS表的select语句Q仅仅返回Customercȝ代理cȝ实例Q这个代理类L以下特征Q?br />
Q?Q?由Hibernate在运行时动态生成,它扩展了Customerc,因此它承了Customercȝ所有属性和ҎQ但它的实现对于应用E序是透明的?br /> Q?Q?当Hibernate创徏Customer代理cd例时Q仅仅初始化了它的OID属性,其他属性都为nullQ因此这个代理类实例占用的内存很?br /> Q?Q当应用E序W一ơ访问Customer代理cd例时Q例如调用customer.getXXX()或customer.setXXX()ҎQ, Hibernate会初始化代理cd例,在初始化q程中执行select语句Q真正从数据库中加蝲Customer对象的所有数据。但有个例外Q那是? 应用E序讉KCustomer代理cd例的getId()ҎӞHibernate不会初始化代理类实例Q因为在创徏代理cd例时OID存在了Q不? 到数据库中去查询?br />
提示QHibernate采用CGLIB工具来生成持久化cȝ代理cRCGLIB是一个功能强大的Java字节码生成工P它能够在E序q行时动态生成扩 ?JavacL者实现Java接口的代理类。关于CGLIB的更多知识,请参考:http://cglib.sourceforge.net/?br />
以下代码先通过
Session的load()Ҏ加蝲Customer对象Q然后访问它的name属性:

tx =
session.beginTransaction();
Customer customer=(Customer)
session.load(Customer.class,new Long(1));
customer.getName();
tx.commit();

在运?/font>session.load ()Ҏ时Hibernate不执行Q何select语句Q仅仅返回Customercȝ代理cȝ实例Q它的OID?Q这是由load()Ҏ的第二个 参数指定的。当应用E序调用customer.getName()ҎӞHibernate会初始化Customer代理cd例,从数据库中加? Customer对象的数据,执行以下select语句Q?br />
select * from CUSTOMERS where ID=1;
select * from ORDERS where CUSTOMER_ID=1;

?lt;class>元素的lazy属性ؓtrueQ会影响
Session的load()Ҏ的各U运行时行ؓQ下面D例说明?br />
1Q如果加载的Customer对象在数据库中不存在Q?/font>Session的load()Ҏ不会抛出异常Q只有当q行customer.getName()Ҏ时才会抛Z下异常:

ERROR LazyInitializer:63
- Exception initializing proxy
net.sf.hibernate.ObjectNotFoundException: No row with the given identifier exists: 1, of class:
mypack.Customer

2Q如果在整个
Session范围内,应用E序没有讉KqCustomer对象Q那么Customer代理cȝ实例一直不会被初始化,Hibernate不会执行Mselect语句。以下代码试囑֜关闭Session后访问Customer游离对象Q?br />
tx =
session.beginTransaction();
Customer customer=(Customer)
session.load(Customer.class,new Long(1));
tx.commit();
session.close();
customer.getName();

׃引用变量customer引用的Customer代理cȝ实例?/font>Session范围内始l没有被初始化,因此在执行customer.getName()ҎӞHibernate会抛Z下异常:

ERROR LazyInitializer:63
- Exception initializing proxy
net.sf.hibernate.HibernateException: Couldnotinitializeproxy-theowningSessionwasclosed

由此可见QCustomer代理cȝ实例只有在当?/font>Session范围内才能被初始化?br />
3Qnet.sf.hibernate.Hibernatecȝ
initialize()静态方法用于在Session范围内显式初始化代理cd例,isInitialized()Ҏ用于判断代理cd例是否已l被初始化。例如:

tx =
session.beginTransaction();
Customer customer=(Customer)
session.load(Customer.class,new Long(1));
if(!Hibernate.isInitialized(customer))
Hibernate.
initialize(customer);
tx.commit();
session.close();
customer.getName();

以上代码?/font>Session范围内通过Hibernatecȝinitialize()Ҏ昑ּ初始化了Customer代理cd例,因此?/font>Session关闭后,可以正常讉KCustomer游离对象?br />
4Q当应用E序讉K代理cd例的getId()ҎӞ不会触发Hibernate初始化代理类实例的行为,例如Q?br />
tx =
session.beginTransaction();
Customer customer=(Customer)
session.load(Customer.class,new Long(1));
customer.getId();
tx.commit();
session.close();
customer.getName();

当应用程序访问customer.getId()ҎӞ该方法直接返回Customer代理cd例的OID|无需查询数据库。由于引用变?customer始终引用的是没有被初始化的Customer代理cd例,因此?/font>Session关闭后再执行customer.getName()ҎQ?Hibernate会抛Z下异常:

ERROR LazyInitializer:63 - Exception initializing proxy
net.sf.hibernate.HibernateException: Couldnotinitializeproxy-theowningSessionwasclosed

解决ҎQ?/font>

׃hibernate采用了lazy=true,q样当你用hibernate查询?q回实际为利用cglib增强的代理类,但其q没有实际填 ?当你在前?利用它来取?getXXX)?q时Hibernate才会到数据库执行查询,q填充对?但此时如果和q个代理cȝ关的session已关闭掉,׃产生U错?
在做一对多Ӟ有时会出?could not initialize proxy - clothe owning Session was sed,q个好像是hibernate的缓存问?问题解决:需要在<many-to-one>里设|lazy="false". 但有可能会引发另一个异常叫

failed to lazily initialize a collection of role: XXXXXXXX, no session or session was closed

此异常解x案请察看本h博客Q?a >http://hi.baidu.com/kekemao1Q的Hibernate异常中的《failed to lazily initialize a collection of role异常?br />
?
解决Ҏ:在web.xml中加?br /> <filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>
     org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    </filter-class>
</filter
<filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>*.do</url-pattern>
</filter-mapping>
可以了;

参考了:
Hibernate与gq加载:

Hibernate对象关系映射提供延迟的与非gq的对象初始化。非延迟加蝲在读取一个对象的时候会与q个对象所有相关的其他对象一赯取出来? q有时会D成百的(如果不是成千的话Qselect语句在读取对象的时候执行。这个问题有时出现在使用双向关系的时候,l常会导致整个数据库都在初始? 的阶D被d来了。当Ӟ你可以不厌其烦地查每一个对象与其他对象的关p,q把那些最昂贵的删除,但是到最后,我们可能会因此失M本想在ORM工具? 获得的便利?/p>


一个明昄解决Ҏ是用Hibernate提供的gq加载机制。这U初始化{略只在一个对象调用它的一对多或多对多关系时才关pd象读取出来。这个过 E对开发者来说是透明的,而且只进行了很少的数据库操作hQ因此会得到比较明显的性能提升。这Ҏ术的一个缺h延迟加蝲技术要求一? Hibernate会话要在对象使用的时候一直开着。这会成为通过使用DAO模式持久层抽象出来时的一个主要问题。ؓ了将持久化机制完全地抽象出来Q所 有的数据库逻辑Q包括打开或关闭会话,都不能在应用层出现。最常见的是Q一些实C单接口的DAO实现cd数据库逻辑完全装h了。一U快速但是笨? 的解x法是攑ּDAO模式Q将数据库连接逻辑加到应用层中来。这可能对一些小的应用程序有效,但是在大的系l中Q这是一个严重的设计~陷Q妨了pȝ? 可扩展性?/p>

在Web层进行gq加?/p>

q运的是QSpring框架为Hibernate延迟加蝲与DAO模式的整合提供了一U方便的解决Ҏ。对那些不熟悉Spring? Hibernate集成使用的hQ我不会在这里讨多的l节Q但是我你去了解Hibernate与Spring集成的数据访问。以一个Web应用? 例,Spring提供了OpenSessionInViewFilter和OpenSessionInViewInterceptor。我们可以随意选择 一个类来实现相同的功能。两U方法唯一的不同就在于interceptor在Spring容器中运行ƈ被配|在web应用的上下文中,而Filter? Spring之前q行q被配置在web.xml中。不用哪个Q他们都在请求将当前会话与当前(数据库)U程l定时打开Hibernate会话。一旦已l? 定到U程Q这个打开了的Hibernate会话可以在DAO实现cM透明C用。这个会话会为gq加载数据库中值对象的视图保持打开状态。一旦这个逻辑? 囑֮成了QHibernate会话会在Filter的doFilterҎ或者Interceptor的postHandleҎ中被关闭。下面是每个l? 件的配置CZQ?/p>


Interceptor的配|?

<beans>
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="openSessionInViewInterceptor"/>
</list>
</property>
<property name="mappings">

</bean>

<bean name="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
</beans>

Filter的配|?/p>

<web-app>

<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
</filter-class>
</filter>

<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*. spring </url-pattern>
</filter-mapping>

</web-app>


实现Hibernate的Dao接口来用打开的会话是很容易的。事实上Q如果你已经使用了Spring框架来实C的Hibernate Dao,很可能你不需要改变Q何东ѝ方便的HibernateTemplate公用lg使访问数据库变成菜一,而DAO接口只有通过q个lg才可? 讉K到数据库。下面是一个示例的DAOQ?/p>


public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO {

public Product getProduct(Integer productId) {
return (Product)getHibernateTemplate().load(Product.class, productId);
}

public Integer saveProduct(Product product) {
return (Integer) getHibernateTemplate().save(product);
}

public void updateProduct(Product product) {
getHibernateTemplate().update(product);
}
}

在业务逻辑层中使用延迟加蝲

即在视囑֤面,Spring框架也通过使用AOP 拦截? HibernateInterceptor来得gq加载变得很Ҏ实现。这个Hibernate 拦截器透明地将调用配置在Spring应用E序上下文中的业务对象中Ҏ的请求拦截下来,在调用方法之前打开一个Hibernate会话Q然后在Ҏ执行 完之后将会话关闭。让我们来看一个简单的例子Q假设我们有一个接口BussinessObjectQ?/p>


public     interface    BusinessObject     {
public     void    doSomethingThatInvolvesDaos();
}
cBusinessObjectImpl实现了BusinessObject接口:

public     class    BusinessObjectImpl    implements    BusinessObject     {
public     void    doSomethingThatInvolvesDaos()     {
//    lots of logic that calls
//    DAO classes Which access
//    data objects lazily  
}  
}  


通过在Spring应用E序上下文中的一些配|,我们可以让将调用BusinessObject的方法拦截下来,再o它的Ҏ支持延迟加蝲。看看下面的一个程序片D:


<beans>
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="businessObjectTarget" class="com.acompany.BusinessObjectImpl">
<property name="someDAO"><ref bean="someDAO"/></property>
</bean>
<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"><ref bean="businessObjectTarget"/></property>
<property name="proxyInterfaces">
<value>com.acompany.BusinessObject</value>
</property>
<property name="interceptorNames">
<list>
<value>hibernateInterceptor</value>
</list>
</property>
</bean>
</beans>

当businessObject被调用的时候,HibernateInterceptor打开一个Hibernate会话Qƈ调用请求传递给 BusinessObjectImpl对象。当BusinessObjectImpl执行完成后,HibernateInterceptor透明地关闭了 会话。应用层的代码不用了解Q何持久层逻辑Q还是实C延迟加蝲?/p>


在单元测试中试延迟加蝲

最后,我们需要用J-Unit来测试我们的延迟加蝲E序。我们可以轻易地通过重写TestCasecM的setUp和tearDownҎ来实现这个要求。我比较喜欢用这个方便的抽象cM为我所有测试类的基cR?/p>


public abstract class MyLazyTestCase extends TestCase {

private SessionFactory sessionFactory;
private Session session;

public void setUp() throws Exception {
super.setUp();
SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory");
session = SessionFactoryUtils.getSession(sessionFactory, true);
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));

}

protected Object getBean(String beanName) {
//Code to get objects from Spring application context
}

public void tearDown() throws Exception {
super.tearDown();
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);
}
}




苏醄 2007-09-12 17:15 发表评论
]]>
试 hibernate 性能 驱动 jdbc 数据?版本 数据 http://www.tkk7.com/sutao/articles/138675.html苏醄苏醄Wed, 22 Aug 2007 10:45:00 GMThttp://www.tkk7.com/sutao/articles/138675.htmlhttp://www.tkk7.com/sutao/comments/138675.htmlhttp://www.tkk7.com/sutao/articles/138675.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/138675.htmlhttp://www.tkk7.com/sutao/services/trackbacks/138675.html
lifejoy|友写了D|试程序,用Hibernate作ؓ持久手段试了大数据量写入MySql数据库的性能。程序主要用了一个@环嵌套,最里层? 环ؓ扚w插入记录的代码,每一Ҏ1000条记录,最外层循环为批ơ的控制Q一共@?00ҎQ这hȝ数据写入量ؓ1000x100共十万记录。从 lifejoy的测试数据看Q用JDBC直接写的速率?00-800?U,而用Hibernate写的速率会从一开始的300多条降至几十条每U,q? 个差距非怹大,难怪lifejoy使用?#8220;暴差”q一非常使h触目惊心的语a?



Hibernate 的写入性能到底如何Q真的到?#8220;暴差”q样的地步么Q其性能与JDBC直写相比Q到底差距多大?q些个问题,通过google l果Q众说纷U,莫衷一是,在台湾JavaWorld论坛上,有网友脓ZHibernate比JDBC性能更加优越的测试结果分析图Q也有很多网友在? 病Hibernate在ORM的同时׃性能Q到底真相在何方Q由于今q做了一个基于Oracle的大型系l,需要支撑高q发数据讉K量,在决定系l架 构的时候,首席架构师选择了iBatisQ而放弃了HibernateQ其中一个最大的考虑是q个性能因素Q可惜当初没有进行技术实际论证,于是有了? 天的q个“?#8221;Q打通过实际试l果来验证一下Hibernate的性能情况Q以澄清如下问题Q?

<!--[if !supportLists]-->1. <!--[endif]-->Hibernate ORMd与JDBC方式d在性能上孰优孰劣?

<!--[if !supportLists]-->2. <!--[endif]-->优势多少Q劣势又是几何?



依照lifejoy的思\下写以下一D代码:



package com.gmail.newmanhuang.learnhibernate;

import java.util.Iterator;

import java.util.List;

import org.hibernate.SessionFactory;

import org.hibernate.Session;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

import org.hibernate.Criteria;

import org.hibernate.criterion.Expression;

import com.gmail.newmanhuang.learnhibernate.model.Person;

import java.sql.*;



public class LearnHibernateMain {



private Configuration config;

private SessionFactory sessionFactory;

private Session session;



public static void main(String[] args) {

LearnHibernateMain lh=new LearnHibernateMain();

//用hibernate创徏10000条记录,?0ơ插入,每次1000条,?00条记录做一ơ批量插?

//lh.createPersons(10, 1000, 100);

//用jdbc直接创徏10000条记录,?0ơ插入,每次1000条,?00条记录做一ơ批量插?

lh.createPersonsByJDBC(10, 1000,100);

}





//用hibernate创徏person记录, loopNum为@环插入的ơ数QbatchNum1为每ơ@环插入的记录敎ͼbatchNum2为物理批量插入记录数

private void createPersons(int loopNum,int batchNum1,int batchNum2){

setup();

System.out.println("hibernate record creating testing.\r\n"

+ "loop times:" + loopNum + "\r\nbatch number:" + batchNum1);



for(int i=0;i<loopNum;i++){

try {

Thread.sleep(50);//休眠

} catch (InterruptedException e) {

e.printStackTrace();

}

long fPoint=System.currentTimeMillis();

Transaction tx = session.beginTransaction();

for(int j=0;j<batchNum1;j++){

Person person = new Person();

person.setName("name-" + i +"-"+ j);

person.setAge(new Integer(25));

session.save(person);

//batch flush

if ( j % batchNum2 == 0 ) {//执行物理扚w插入

session.flush();

session.clear();

}

}

tx.commit();

long tPoint=System.currentTimeMillis();

//打印插入batchNum1条记录的速率(?U?

System.out.println(

"the " + i + " batch" + "(" + batchNum1 +") rcds/s:"

+ ((double)batchNum1/(tPoint-fPoint))*1000);

}

teardown();

}



//用jdbc创徏person记录, loopNum为@环插入的ơ数QbatchNum1为每ơ@环插入的记录敎ͼbatchNum2为物理批量插入记录数

private void createPersonsByJDBC(int loopNum,int batchNum1,int batchNum2){

System.out.println("JDBC record creating testing.\r\n"

+ "loop times:" + loopNum + "\r\nbatch number:" + batchNum1);

Connection conn=getDBConn();

try{

PreparedStatement pstmt=conn.prepareStatement("insert into person(name,age) values(?,?)");

for(int i=0;i<loopNum;i++){

try {

Thread.sleep(50);//休眠

} catch (InterruptedException e) {

e.printStackTrace();

}

long fPoint=System.currentTimeMillis();

conn.setAutoCommit(false);

for(int j=0;j<batchNum1;j++){

String name="name-" + i +"-"+ j;

pstmt.setString(1, name);

pstmt.setInt(2, 25);

pstmt.addBatch();

if(j%batchNum2==0){//执行物理扚w插入

pstmt.executeBatch();

conn.commit();

}

}

pstmt.executeBatch();

conn.commit();

conn.setAutoCommit(true);

long tPoint=System.currentTimeMillis();

//打印插入batchNum1条记录的速率(?U?

System.out.println(

"the " + i + " batch" + "(" + batchNum1 +") rcds/s:"

+ ((double)batchNum1/(tPoint-fPoint))*1000);

}

pstmt.close();

}catch(Exception x){

try{

conn.close();

}catch(Exception x1){



}

}

}



//获取JDBCq接

private Connection getDBConn(){

Connection conn=null;

try {

Class.forName("org.gjt.mm.mysql.Driver");

conn=DriverManager.getConnection("jdbc:mysql://localhost/learnhibernate", "root", "");

} catch (Exception x) {



}

return conn;

}



//初始化hibernate数据库环?

private void setup(){

config = new Configuration().configure();

sessionFactory = config.buildSessionFactory();

session = sessionFactory.openSession();

}



//销毁hibernate数据库环?

private void teardown(){

session.close();

sessionFactory.close();

}

}






? 试环境主要ؓQJ2SDK1.4.2_04, MySql4.1.9-Max, Hibernate3.1, IBM Thinkpad R32-P4 1.8G, 512M MemoryQMySql中待插表的类型ؓINNODBQ以支持事务QISAMcd表的d速率要远高于INNODBQ这里不采用ISAM是因Z支持? 务?



主要分ؓ三个试场景Q以下ؓ三个场景的测试记录和分析Q?



试场景一Q?

############# 试环境一 #######################

mysql版本Q?.1.9-max

jdbc驱动Qmysql-connector-java-3.1.11-bin.jar

hibernate: 3.1



################################################



1.hibernate扚w插入Q创?0000条记录,?0ơ插入,每次1000条,?00条记录做一ơ批量插入操?

试记录Q?

======================================================================

hibernate record creating testing.

loop times:10

batch number:1000

the 0 batch(1000) rcds/s:172.1763085399449

the 1 batch(1000) rcds/s:214.73051320592657

the 2 batch(1000) rcds/s:302.6634382566586

the 3 batch(1000) rcds/s:321.13037893384717

the 4 batch(1000) rcds/s:318.9792663476874

the 5 batch(1000) rcds/s:316.05562579013906

the 6 batch(1000) rcds/s:318.9792663476874

the 7 batch(1000) rcds/s:317.05770450221945

the 8 batch(1000) rcds/s:317.9650238473768

the 9 batch(1000) rcds/s:314.96062992125985



试l果Q?

hibernate新记录创建^均速率Q~290?U?

======================================================================



2.jdbc扚w插入Q创?0000条记录,?0ơ插入,每次1000条,?00条记录做一ơ批量插入操?

试记录Q?

======================================================================

JDBC record creating testing.

loop times:10

batch number:1000

the 0 batch(1000) rcds/s:812.3476848090983

the 1 batch(1000) rcds/s:988.1422924901185

the 2 batch(1000) rcds/s:1233.0456226880394

the 3 batch(1000) rcds/s:1314.060446780552

the 4 batch(1000) rcds/s:1201.923076923077

the 5 batch(1000) rcds/s:1349.527665317139

the 6 batch(1000) rcds/s:853.9709649871904

the 7 batch(1000) rcds/s:1218.026796589525

the 8 batch(1000) rcds/s:1175.0881316098707

the 9 batch(1000) rcds/s:1331.5579227696405



试l果Q?

jdbc新记录创建^均速率Q~1147?U?

======================================================================





******试环境一l论Qjdbc性能明显优于hibernateQ写入速率比jdbc/hibernate=3.95








试场景二:

############# 试环境?#######################

mysql版本Q?.1.9-max

jdbc驱动Qmysql-connector-java-3.0.11-bin.jarQ注意这里更换了mysql的connectorJ驱动Q!Q)

hibernate: 3.1

################################################



1.hibernate扚w插入Q创?0000条记录,?0ơ插入,每次1000条,?00条记录做一ơ批量插入操?

试记录Q?

======================================================================hibernate record creating testing.

loop times:10

batch number:1000

the 0 batch(1000) rcds/s:536.7686527106817

the 1 batch(1000) rcds/s:504.28643469490675

the 2 batch(1000) rcds/s:1062.6992561105205

the 3 batch(1000) rcds/s:1122.334455667789

the 4 batch(1000) rcds/s:1133.7868480725624

the 5 batch(1000) rcds/s:1122.334455667789

the 6 batch(1000) rcds/s:1008.0645161290322

the 7 batch(1000) rcds/s:1085.7763300760043

the 8 batch(1000) rcds/s:1074.1138560687434

the 9 batch(1000) rcds/s:1096.4912280701756



试l果Q?

新记录创建^均速率Q~974?U?

======================================================================



2.jdbc扚w插入Q创?0000条记录,?0ơ插入,每次1000条,?00条记录做一ơ批量插入操?

试记录Q?

======================================================================

JDBC record creating testing.

loop times:10

batch number:1000

the 0 batch(1000) rcds/s:1231.527093596059

the 1 batch(1000) rcds/s:1406.4697609001407

the 2 batch(1000) rcds/s:2000.0

the 3 batch(1000) rcds/s:1692.047377326565

the 4 batch(1000) rcds/s:1386.9625520110958

the 5 batch(1000) rcds/s:1349.527665317139

the 6 batch(1000) rcds/s:1074.1138560687434

the 7 batch(1000) rcds/s:1386.9625520110958

the 8 batch(1000) rcds/s:1636.6612111292961

the 9 batch(1000) rcds/s:1814.8820326678765



试l果Q?

新记录创建^均速率Q~1497?U?

======================================================================

******试环境二结论:jdbc性能仍优于hibernateQ写入速率比jdbc/hibernate =1.58






试场景三:

############# 试环境?#######################

mysql版本Q?.1.9-max

jdbc驱动Qmysql-connector-java-3.0.11-bin.jarQ与试环境二用同L驱动Q?

hibernate: 3.1

特别说明Q记录插入不使用事务

################################################



1.jdbc扚w插入Q创?0000条记录,?0ơ插入,每次1000条,?00条记录做一ơ批量插入操作,不用事务(注意q里Q不使用事务Q!Q?

试记录Q?

===========================================================================================

JDBC record creating testing.

loop times:10

batch number:1000

the 0 batch(1000) rcds/s:43.11645755184754

the 1 batch(1000) rcds/s:34.32651379925854

the 2 batch(1000) rcds/s:40.65701740120345

the 3 batch(1000) rcds/s:62.44925997626928

the 4 batch(1000) rcds/s:69.58942240779402

the 5 batch(1000) rcds/s:42.45743641998896

the 6 batch(1000) rcds/s:44.420753375977256

the 7 batch(1000) rcds/s:44.44049417829527

the 8 batch(1000) rcds/s:56.63797009515179

the 9 batch(1000) rcds/s:71.73601147776183



试l果Q?

新记录创建^均速率Q~50?U?

======================================================================




试l果分析Q?

1. 在同{测试环境和条g下,hibernate优于jdbcq种说法是错误的Q从试l果来看Q?jdbc要优于hibernateQ这从理Z是可以理解的Qhibernate的基是jdbcQ它不可能优于jdbc?

2. 影响数据库操作性能的因素很多,主要包括Q?

1)数据库自w?

如mysql表类型,是ISAMq是innodb

2)数据库驱?

? 试数据和结果看Qmysql?.0.11版本的驱动显然更适合于mysql4.1.9版本的数据库Q而高版本?.1.11用于 hibernate的插入操作则会p3.5倍的执行效率Q另外,l过W者测试,?.1.11版本的驱动中Q用与不用批?batch)插入操作 居然没有M区别Q这也能解释一些技术论坛上提到的hibernate批处理操作有时候会实效q个令h困惑的问题?

3)操作数据库的E序本n

试环境3表明Q当mysql的表cd为innodbӞ即是采用JDBC直接写的方式Q不采用事务方式插入记录Q写入速率几乎?#8220;蜗?#8221;Q~50?U)Q这可以说是“杀手”的因素了?



l论Q?

<!--[if !supportLists]-->1. W者估计在大数据量写入状况下,Hibernate的性能损失?0%-35%左右<!--[endif]-->

<!--[if !supportLists]-->2. 对于要获取高性能数据d的系l,不推荐用Hibernate的ORM方式q行数据d?lt;!--[endif]-->

<!--[if !supportLists]-->3. 性能的优劣除了所采用的技术决定外Q更取决于用技术的人,比如在测试环境三中,不采用事务方式写数据Q其速度直不能以“暴差”来Ş容,xq样一U情 况,让你d一辆法拉利F1赛RQ你一定能惌得到你驾驶的速度。:Q?lt;!--[endif]-->



后记Q?

? q行试的时候,起初W者用的JDBC驱动是J/Conncector 3.1.11版本Q发现Hibernate的批量写讄Ҏ不v作用Q是否用批量写Ҏ没有差别,在一些网站上面也发现有类似的疑问Q经q更换ؓ 3.0.x版本驱动后,扚w写才生效Q而且无论是Hibernate方式q是JDBC方式下,写记录的性能明显提升Q表?.0.X的驱动更适合? MySql4.1Qؓ什么高版本?.1.11反而在低版本数据库上面表现Z效?W者在安装Rollerq个Apache孵化器blog目的时候,? 对安装指g推荐使用3.0.X版本来匹配MySql4.1数据库这个问题比较疑惑,可惜Roller的InstallGuid没有做具体解释,感兴的 |友可以到Roller|站的wiki上去弄清楚这个问题,q把{案做个回复Q非常感谢。这个插曲还说明了一个道理—?#8220;升qL好事”?/span>

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1339954




苏醄 2007-08-22 18:45 发表评论
]]>
Hibernate 要点http://www.tkk7.com/sutao/articles/134892.html苏醄苏醄Tue, 07 Aug 2007 02:58:00 GMThttp://www.tkk7.com/sutao/articles/134892.htmlhttp://www.tkk7.com/sutao/comments/134892.htmlhttp://www.tkk7.com/sutao/articles/134892.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/134892.htmlhttp://www.tkk7.com/sutao/services/trackbacks/134892.html注册?a target="systemIframe" class="textIcon" title="" id="login">d?a target="_blank" class="textIcon" id="newArticle">发表文章
 
2007-02-05 23:10:55
属?br> 1  unsaved-value:对联对象进行数据保存时QHibernate根据这个值来判断对象是否需要保存;先从U联对象中取出idQ如果id? unsave-value值相{,则认为对象尚未保存,否则认ؓ对象已经保存Q这里的保存指的是insertQ而不是updateQ?br> ;在隐式保存的情况下,Hibernate用目标对象的id值和此值比较,如果相等则insertQ否则不insert
2  hbm.xml文g的class标签中有一个polymorphismQ?explicit"属性,它的作用是:声明一个显式多态关p,声明为显式多态的cd有在代码中(?list object=createQuery("from TuserProfile").list();q里昑ּ指明了TuserProfilec)明确指定cd的时候才会返回此cd?
  如果要返回对应整个数据库中所有库表记录的数据对象Q可? List obj=createQuery("from object").list();但不会返回在映射文g中具有polymorphismQ?explicit"定义的类的实?br> 3 inverse:用于在设|双向一对多关系时设|维护两个实体关pȝ一?inverse=false的一方负责维护双方关p?在one-to-many关系中,常将many一方设为false?br> 4 cascade:指的是当LҎ行操作时Q关联对象(被动方)是否同步执行同一操作。例如对L对象调用save-update或deleteҎӞ 是否同时对关联对象(被动方)q行sava-update或deleteQ设定ؓall则代表无Z控方执行M操作 QInsert/update/delete...Q都对其兌cL行同L操作
           ;Ҏ此属性的讄对相兌的对象采取相应的操作
   cascade="all-delete-orphan"处理方式:
   当保存当前对象时保存相关联的对象Q相当于cascade="save-update"
   当删除当前对象时删除相关联的对象Q相当于cascade="delete"
   当双方存在父子关pLQ如果解除了子与父的关系则删除和父方解除关系的子方记?br>  (当关联双方存在父子关pLQ就可以把父方的cascade设ؓall-delete-orphan)
 5 ?lt;property>标签中的access属性说明:
   形式<property name="name" column="name" access="field/property"/>
  access默认为propertyQ意思是QHibernate不是直接讉K持久化类中的name属性,而是讉KsetName()和getName()Ҏ;
  access="field",意思是:Hibernate不访问setName()和getName()ҎQ而是直接讉K持久化类中的name属?br> 6 hbm.xml文g的class标签中有一个polymorphismQ?explicit"属性,它的作用是:声明一个显式多态关p,声明为显式多态的cd有在代码中(?list object=createQuery("from TuserProfile").list();q里昑ּ指明了TuserProfilec)明确指定cd的时候才会返回此cd?
  如果要返回对应整个数据库中所有库表记录的数据对象Q可? List obj=createQuery("from object").list();但不会返回在映射文g中具有polymorphismQ?explicit"定义的类的实?/div>
  Ҏ
1  加蝲数据的get和loadҎ区别:
   a 如果未能发现W合条g的记录,getҎq回null,loadҎ抛出一个ObjectNotFoundException异常
   b load可以q回实体的代理类实例Qget永远直接q回实体c?br>     代理cd?
    实体c?
   c load要在内部~存和二U缓存中搜烦现有数据Qget则仅在内部缓存中q行数据查找(Ҏid查找)Q如果在内部~存中没有找到数据则直接从数据库中读?br>  
    内部~存Q一U缓存)Q其中保持了session当前所有关联实体的数据
    二~存:存在于SessionFactory层次Q由当前所有本SessionFactory构造的session实例׃n
2 session.find(hql,parameterValue,Hibernate Type of parametervlaue)和session.iterator(hql,parameterValue,Hibernate type of parameterValue) Ҏ的区?
 session.find()q回的是List集合Qsession.find() 执行相应SQL后返回记录ƈ构造相应的实体对象Q再其U_~存.find()不会对缓存进行数据查询,而是直接从数据库取记录,对于~存只写不读
 session.iterator()q回的是Iterator集合Q执行N+1ơ查询出所有符合条件的记录Q首先查询满x件的记录idQ再Ҏid 查询所有记录;iterator首先在本地缓存中Ҏid查找对应的实体对象是否存?cMsession.load())Q若存在则以此数据对象作为结 果返回;若未扑ֈQ则执行相应SQL语句从数据库获得对应的记?q构建完整数据对象,再将其纳入缓?br> 3 ~存对象的移?br>   session.evict(user)----从一U缓存中U除对象
  sessionFactory.evict(Tuser.class,user.getId())-------从二U缓存中U除对象;二~存可以讑֮最大数据缓存量Q达到峰值时自动对缓存中的较老数据进行移除;也可以手工移除(如前Q?br> 4 session.save()先在一U缓存中查询要保存的对象Q若扑ֈ则认为对象处于持久状态;不会把对象放在二U缓存,而是攑֜一U缓?br>   session.update()先在一U缓存中查询要保存的对象Q若扑ֈ则认为对象处于持久状态;在session.flush()时执行update的SQL语句(transaction.commit在真正提交数据库事务前会调用session.flush)
  saveorupdate()无需用户判断对象的状态,其自动判断再执行save或者update
5 saveorupdate()Ҏ说明:该方法包含了save()与update()Ҏ的功能,如果传入的参数是临时对象Q就调用save()ҎQ如 果传入的参数是游d象,p用update()ҎQ如果传入的是持久化对象Q那q接返?saveorupdate()Ҏ如何判断一个对象是处于 临时状态还是游d象根据的是以下条Ӟ满其一卛_:
 1.java对象的ID取gؓnull
 2.java对象hversion属性ƈ且取gؓnull
 3.在映文件中?lt;id>元素讄了undaved-value属性,q且ID取gundaved-value属性值匹配?br>  4.在映文件中为version属性设|了unsaved-value属性,q且version属性取gunsaved-value属性值匹?
 5.自定义了Hibernate的Interceptor实现c,q且Interceptor的isUnsaved()Ҏq回true.
实体对象的三U状?br> java中,对象不引用Q何对象且不被M对象引用Ӟ׃被JVM回收Q此时该对象才结束生命周?
session~存:session~存其实是session的实现类sessionImp中定义的Map集合Q以对象ID为键Q以对象为值的形式保存.
1 Transient(自由状?:刚刚用new语句创徏Q还没有被持久化Q不处于session的缓存中。即实体对象在内存中是自由存在的Q它与数据库中的记录无关Q处于时状态的java对象被称Z时对?
    特征:1.不处在session的缓存中Q也可以_不被M一个session实例兌.
  2.在数据库中没有对应的记录.
 在以下情况下Qjava对象q入临时状?
  1.当通过new语句刚创Z一个java对象Q它处于临时状态,此时不和数据库中的Q何记录对?
  2.session的delete()Ҏ能一个持久化对象或游d象{变ؓ临时对象。对于游d象,delete()Ҏ从数据库中删除与它对应的记录;对于持久化对象,delete()Ҏ从数据库中删除与它对应的记录Qƈ且把它从session~存中删?
 
2 Persistent(持久状?:已经被持久化Q加入到了session~存中。实体对象处于由Hibernate框架所理的状态,q种状态下Q实? 对象的引用被U_Hibernate实体容器中加以管?处于Persistent状态的对象Q其变更由Hibernate固化到数据库?br> 何时变ؓ持久状?当实体对象处于自q态时Q通过Session.saveҎ可将其{换ؓPersistent状态,如果一个实体对象是? Hibernate加蝲(如通过Session.loadҎ获得),那它也处于Persistent状?处于持久化状态的实体即没有调用 session.save()Ҏq行数据持久化,而只用了tx.commit()也会被保存到数据?br> 持久化对象的特征:
 1.位于一个session实例的缓存中Q也可以_持久化对象L被一个session实例兌.
 2.持久化对象和数据库中的相兌录对?br>  3.session在清理缓存时Q会Ҏ持久化对象的属性变化,来同步更新数据库
 3 Detached(游离状?:已经被持久化Q但不处于session~存当中.对应的Session实例关闭之后Q此对象处于游ȝ?br>  例:
 Tuser user=new Tuser();
 user.setName("Emma");//此时实体对象user处于游离状?br>  Tansaction tx=session.beginTransaction();
 session.save(user);//此时实体对象user已经由HibernateU_理容器Q处于Persistent状?br>  tx.commit();
 session.close();//(Tag)     实体对象user此时状态ؓDetachedQ因Z其关联的session已经关闭   
3 游离对象的特?
 1.不再位于session~存中,也可以说Q游d象不实被session兌.
 2.游离对象是由持久化对象{变来的,因此在数据库中可能还存在与它对应的记?只要没删除该记录)
4 Transient状态和Detached状态的相同之处:两者都不被session兌.两者的区别:游离对象是由持久对象转变q来的,因此可能在数? 库中q存对应的记录,而时对象在数据库中没有对应的记?Detached对象可以再次与某个Session实例相关联而成为Persistent? ?如下所C?br> 接Tag?
Transaction tx2=session2.beginTransaction();
session2.update(user);//此时处于Detached状态的user对象再次借助session2由HibernateU_理容器Q恢复Persistent状?br> user.setName("Eric");
tx2.commit();//׃user对象再次处于Persistent状态,因此其属性变更将自动由Hibernate固化到数据库
5 Transient状态的对象与数据库中记录ƈ不存在对应关p,它所包含的数据信息仅是上面的user.setName("Emma")q点而已Q? Session.save()执行后,Hibernate对user对象q行了持久化Qƈ为其赋予了主键|q时user对象׃库表中具备相同id值的 记录相关?所以,Transient状态的user对象与库表中的数据缺乏对应关p,而Detached状态的user对象Q却在库表中存在相对应的? ?׃键惟一定)Q简而言之,Transient状态中的实体对象,无主键信息,而Deatched状态的实体对象包含了其对应数据库记录的主键?
实体对象从Persistent状态{变ؓTransient状态一般由session.deleteҎ完成
6 Collection在判断两个对象是否相{的时候,会首先调用对象的hashCodeҎQ如果hashCode相同的话Q 再调用equalsҎQ如果两ơ判断均为真Q则认ؓҎ的两个对象相{?/div>

兌关系
*********************一对多关系中,一?lt;set>的说?********************************************
1 ?lt;set>中同时设|lazy和outer-join属性时Q如果两者都为false则采用立x?因ؓouter-join="false"则不采用q切左外q接Q但lazy="false"则是指采用立x索策?;
如果lazy和outer-join其中一个ؓfalse另一个ؓtrue(不管谁是false谁是true),则以讄为true的那一个ؓ?? lazy=true,outer-join=false则是采用延迟?相反采用q切左外q接);如果两者均为true则同lazy=false, outer-join=true(即采用迫切左外连接,outer-join优先U比lazy?;find()Ҏ会忽略outer-join属性,? outer-join对findҎ无效;
如果<set>中设有lazy?lt;class>中也设有lazy属性,则是?lt;class>中的为准;
    对于get和findҎ均是采用立即?与lazy的设|无?br> 2 <set>中的batch-size属性可以理解ؓ:在加?lt;set>中的<one-to-many>中的classcd象时Q要初始化的对象数目Q以便在后面再次需要初始化时不需要再讉K数据库,从而提高数据访问速度
3 <set>中一般要讄Qlazy=true,outer-join="true",batch-size设ؓ要在子方初始化的对象个数(一般ؓQ?-10)
************************多对一关系中,多方的说?*****************************888
1(设一方[customer.hbm.xml]的class中的lazy为A;多方[order.hbm.xml]?lt;many-to-one>中的outer-join为B)
 A=true,B=auto,则对于order.hbm.xml?lt;many-to-one>中的class指向的对象[customer]采用延迟索,否则用迫切左外连接检?br>  A=false,B=true,对于order兌的customer采用q切左外q接?br>  A=true,B=false 对于order兌的customer对象采用延迟索,否则采用立即?br>   l论Q当A=trueӞ则B无论设ؓ什么均按照A的设|进行检索,只有当A=falseӞ才按B的设|进行检?A的优先大于B)
2.hibernate.max_fetch_deepth:在迫切左外连接的多层数据表的索中讄从第一层检索表开始的索深?即从W一层检索表开始要索几层从W一层开始的索表)
Java集合
1.Set 集合中的对象不按特定方式排序Q且没有重复对象;
 该接口主要有两个实现cHashSet和TreeSet?br>  HashSetcL照哈希算法来存取集合中的对象Q存取速度比较快。HashSetc还有一个子cLinkedHashSetc,它不仅实C哈希法Q且实现了链表数据结构。TreeSetcdCSortedSet接口  Q具有排序功?
 Z保证HashSet能正常工作,要求当两个对象用equals()Ҏ比较的结果ؓ相等Ӟ其哈希码也相{?卛_果覆盖了equals()ҎQ也应该覆盖hashCode()Ҏ
Set set = new HashSet();
  String s1 = new String("hello");
  String s2 = s1;
  String s3 = new String("world");
  set.add(s1);
  set.add(s2);
  set.add(s3);
  System.out.println("set的元素个敎ͼ" + set.size());//==2
2 List List的主要特征是其对象以U性方式存储,集合中允许存N复对象。List接口主要的实现类有:LinkedListQArrayList? LinkedList采用链表数据l构Q而ArrayList代表大小可变的数l?List接口q有一个实现类VectorQ其功能和ArrayList 怼Q两者的区别在于QVectorcȝ实现了同步机Ӟ而ArrayList没有使用同步机制.
 List寚w合中的对象按索引位置排序Q允许按照对象在集合中的索引位置索对?br>  List的iterator()Ҏ和Set的iterator()Ҏ均返回Iterator对象Q通过Iterator对象Q可以遍历集合中的所有对?/div>
3 Map:MapQ映)是一U把键对象和值对象进行映的集合Q其每一个元素都包含了一寚w对象和值对象,而值对象仍可以是Mapcd;向Map集合中加入元素时Q必L供一寚w对象和值对象,从Map集合中检索元素时Q只要给出键对象Q就会返回对应的值对象?/div>
Map map=new HashMap();
map.put("1","Monday");
map.put("2","Tuesday"); 
map.put("3","Wendsday");
map.put("4","Thursday");
System.out.println("Map试==="+map.get("2"));//=Tuesday
Map集合中的键对象不允许重复Q即L两个键对象通过equals()Ҏ比较的结果都是false,对于值对象则没有惟一性的要求Q可以将L多个键对象映到同一个值对象上,但是后加入的值将会覆盖先加入的?
Map有两U比较常用的实现QHashMap和TreeMap。HashMap按照哈希法来存取键对象有很好的存取性能
多对一关系中多方的配置
<many-to-one  name="customer"  column="customer_id" class="pkg.customer"/>
<set
    name="order"
    cascade="sava-update"
   inverse="true">
<key column="customer_id"/>
<one-to-many class="pkg.order"/>
</set>



苏醄 2007-08-07 10:58 发表评论
]]>hibernate二~存与一U缓存的关系http://www.tkk7.com/sutao/articles/134888.html苏醄苏醄Tue, 07 Aug 2007 02:55:00 GMThttp://www.tkk7.com/sutao/articles/134888.htmlhttp://www.tkk7.com/sutao/comments/134888.htmlhttp://www.tkk7.com/sutao/articles/134888.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/134888.htmlhttp://www.tkk7.com/sutao/services/trackbacks/134888.html阅读全文

苏醄 2007-08-07 10:55 发表评论
]]>
վ֩ģ壺 Ļ| Ʒþþþþþþ| Ұһ| AVרAv| ѹۿƵ| ĻӰȫѰ| ѡӰ | AVպAVһ| Ƶ| Ӱվ| ޾Ʒþþþ66| ĻӰѹۿַ| | 69ƷƵ| ھƷ߹ۿ| þùֱ| һһëƬѲ| HƬaaaֱ| ޾Һ| һƴɫëƬ| պƵ| һӰ| þþþþav| ɫAVɫһ| 2022Ļ| ޹Ʒպ| Ů߲| ?v˿߹ۿ| պѲ| ղһ| ҹƵ| ëƬվ߹ۿ| Ʒһ| ƵvƬwww| ĻѾþӰԺ| ޳aһ| ޹Ʒ˾þ | ҹպһ| ޹v߹ۿ| ˳ɵӰվƷ | պAVһ |