??xml version="1.0" encoding="utf-8" standalone="yes"?> cascade属性ƈ不是多对多关pM定要用的Q有了它只是让我们在插入或删除对像时更方便一些,只要在cascade的源头上插入或是删除Q所有cascade的关pd会被自己动的插入或是删除。便是ؓ了能正确的cascadeQunsaved-value是个很重要的属性。Hibernate通过q个属性来判断一个对象应该saveq是updateQ如果这个对象的id是unsaved-value的话Q那说明q个对象不是persistence object要saveQinsert)Q如果id是非unsaved-value的话Q那说明q个对象是persistence objectQ数据库中已存在Q,只要updatep了。saveOrUpdateҎ用的也是q个机制?/p>
Q、到底在哪用inverse="ture"? inverse属性默认是false的,是说关pȝ两端都来l护关系。这个意思就是说Q如有一个Student, Teacher和TeacherStudent表,Student和Teacher是多对多对多关系Q这个关pȝTeacherStudentq个表来表现。那么什么时候插入或删除TeacherStudent表中的记录来l护关系呢?在用hibernateӞ我们不会昄的对TeacherStudent表做操作。对TeacherStudent的操作是hibernate帮我们做的。hibernate是看hbm文g中指定的??l护关系Q那个在插入或删??Ӟ׃处发对关p表的操作。前提是"?q个对象已经知道q个关系了,是说关pd一头的对象已经set或是add??q个对象里来了。前面说qinverse默认是falseQ就是关pȝ两端都维护关p,对其中Q一个操作都会处发对表系表的操作。当在关pȝ一_如Student中的bag或set中用了inverseQ?true"Ӟ那就代表关系是由另一关维护的QTeacherQ。就是说当这插入StudentӞ不会操作TeacherStudent表,即Student已经知道了关pR只有当Teacher插入或删除时才会处发对关p表的操作。所以,当关pȝ两头都用inverse="true"是不对的Q就会导致Q何操作都不处发对关系表的操作。当两端都是inverse="false"或是default值是Q在代码对关pLC的l护也是不对的,会导致在关系表中插入两次关系?/p>
在一对多关系中inverse更有意义了。在多对多中Q在哪端inverse="true"效果差不多(在效率上Q。但是在一对多中,如果要一方维护关p,׃使在插入或是删除"一"Ҏ去update"?方的每一个与q个"一"的对象有关系的对象。而如果让"?斚wl护关系时就不会有update操作Q因为关pd是在多方的对象中的,直指插入或是删除多方对象p了。当然这时也要遍??方的每一个对象显C的操作修关pȝ变化体现到DB中。不怎样_q是??方维护关pL直观一些?/p>
Q、cascade和inverse有什么区别? 可以q样理解Qcascade定义的是关系两端对象到对象的U联关系Q而inverse定义的是关系和对象的U联关系?/p>
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=741468 详见Qhttp://www.bczs.net/xml/2005/12/21/4473293.xml
http://welcomejianghome.spaces.msn.com/blog/cns!3196CAE67CDF2316!149.entry
all : 所有情况下均进行关联操作? all的意思是save-update + delete
noneQ所有情况下均不q行兌操作。这是默认倹{?
save-update:在执行save/update/saveOrUpdate时进行关联操作?
deleteQ在执行delete时进行关联操作?
all-delete-orphan 的意思是当对象图中生孤儿节Ҏ,在数据库中删除该节点
all比较好理?举个例子说一下all-delete-orphan:
Category与Item是一对多的关p?也就是说CategorycM有个Setcd的变量items.
举个例子,现items中存两个Item, item1,item2,如果定义关系为all-delete-orphan
当items中删除掉一个item(比如用remove()Ҏ删除item1),那么被删除的Itemcd?
变成孤儿节?当执行category.update(),或session.flush()?
hibernate同步~存和数据库,会把数据库中item1对应的记录删?
]]>
表UserQAddress是一对多的关p?br />UserBean中有一个addresses的Set
现在要查询出q样的UserQ拥有Address中门牌doorplate?642"的UserQ?br />现在DB中只有一个这LUserQ这个User拥有门牌doorplate?642"的Address五个~~
创徏DetachedCriteria 的语句如下:
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(User.class);
detachedCriteria.createCriteria("?).add(Restrictions.like("doorplate","642"));
实际查询语句如下Q?br />
List list = getHibernateTemplate().findByCriteria(queryCriteria);
理论上查询出来的list应该User的list?
ȝ如下
1Q?br />DetachedCriteria addressCriteria = DetachedCriteria.forClass(User.class).createCriteria("addresses");
addressCriteria.add(Restrictions.eq("doorplate","642")):
2Q?br />DetachedCriteria addressCriteria = DetachedCriteria.forClass(User.class).createAlias("addresses", "a");
addressCriteria.add(Restrictions.eq("a.doorplate","642")):
]]>
1
?/span>
select
sum
(t1.useHours)
as
hours1
from
Table1 t1
where
condition1
2
?/span>
select
sum
(t2.useHours)
as
hours2
from
Table2 t2
where
condition2
上面两条语句是在同一个表中根据不同条件查询出两个l果Q比如:
语句1得到l果?0
语句2得到l果?0
我现在希望得C面的l果Q?br />
hours1 hours2
10
20
直接在写sql时做一下数据连l就可以?br />
select
(
select
sum
(t1.useHours)
from
Table1 t1
where
condition1) hours1,
(
select
sum
(t2.useHours)
from
Table2 t2
where
condition2) hours2
当然也可以参考如下的写法:
hql
=
"
select
sum
(
case
when
"
+
whereSql1
+
"
then
(pro.preengageHoursOrSamples
+
pro.adjustOfHours)
else
0
end
)
as
a,";
hql
+=
"
sum
(
case
when
"
+
whereSql2
+
"
then
(pro.preengageHoursOrSamples
+
pro.adjustOfHours)
else
0
end
)
as
b,";
hql
+=
"
sum
(
case
when
"
+
whereSql3
+
"
then
(pro.preengageHoursOrSamples
+
pro.adjustOfHours)
else
0
end
)
as
c";
hql
+=
"
from
PreengageOddPO pro
where
1
=
1
";
]]>
使用Ҏ:
String hql
=
"
select
{pro.
*
}
from
T_ES_PreengageOdd pro
where
1
=
1
";
SQLQuery sqlQuery
=
this.getSession().createSQLQuery(hql);
sqlQuery.addEntity("pro",PreengageOddPO.class);
List list
=
sqlQuery.list();
return
list;
说明:T_ES_PreengageOdd是你数据库中实际的表?
PreengageOddPO是你PO对象,它对应映成表T_ES_PreengageOdd.
SQLQuery sqlQuery1
=
this.getSession().createSQLQuery(
"
select
{ep.
*
}
from
T_ES_Equipment ep
where
ep.CHNNAME
like
:equipname
and
ep.equip_id
=
:equipid");
sqlQuery1.addEntity("ep", EquipmentPO.class);
sqlQuery1.setString("equipname", "
%
pȝ
%
");
sqlQuery1.setString("equipid", "
11020874
");
List result
=
sqlQuery1.list();
if
(result
!=
null
&&
result.size()
>
0
) {
for
(
int
i
=
0
; i
<
result.size(); i
++
) {
EquipmentPO equipmentPO
=
(EquipmentPO) result.get(i);
System.out.println("equipname
===>
"
+
equipmentPO.getChineseName());
}
}
打印l果:
equipname
===>
气质pȝ
]]>
刘艳?Q?/SPAN>
数据持久层的设计目标是ؓ整个目提供一个高层、统一、安全和q发的数据持久机制。完成对各种数据q行持久化的~程工作Qƈ为系l业务逻辑层提供服务。数据持久层提供了数据访问方法,能够使其它程序员避免手工~写E序讉K数据持久?Persistene layer)Q其专注于业务逻辑的开发,q且能够在不同项目中重用映射框架Q大大简化了数据增、删、改、查{功能的开发过E,同时又不丧失多层l构的天然优势,l承延箋J2EEҎ的可伸羃性和可扩展性?O:P>
1 数据持久层及ORM映射框架
W者从事的目中的数据持久层,是基于J2EE体系l构Qƈ采用了Hibernate作ؓ持久映射框架?O:P>
Hibernate是一U新的ORM映射工具Q是JDBC的轻量的对象封装。Hibernate可以用在JDBC可以使用的Q何场合,例如Java应用E序的数据库讉K代码QDAO接口的实现类Q甚臛_以是BMP里面的访问数据库的代码。Hibernate不仅提供了从Javacd数据表之间的映射Q也提供了数据查询和恢复机制。相对于使用JDBC和SQL来手工操作数据库Q用HibernateQ可以大大减操作数据库的工作量?
Hibernate是一个和JDBC密切兌的、独立的对象持久层框Ӟ可以搭配各种App Server、Web Server、EJB Container共同使用QHibernate的兼Ҏ仅同JDBC驱动、底层数据库产品间有一定的关系Q但是和使用它的JavaE序、App Server没有M关系Q也不存在兼Ҏ问题。而且事实表明Hibernate可以和多UWeb服务器或者应用服务器良好集成Q如今已l支持几乎所有的行的数据库服务器(?6U)?O:P>
在较为常用的数据持久Ҏ中,Hibernate无疑是最优秀的,下面是对各种持久Ҏ的比较?O:P>
t 行的数据持久层架构Q?O:P>
Business Layer <-> Session Bean <-> Entity Bean <-> DB
t Z解决性能障碍的替代架构:
Business Layer <-> DAO <-> JDBC <-> DB
t 使用Hibernate来提高上面架构的开发效率的架构Q?O:P>
Business Layer <-> DAO <-> Hibernate <-> DB
我们׃?个架构来作如下分析?O:P>
(1)内存消耗:采用JDBC的架构无疑是最省内存的QHibernate的架构次之,EB的架构最差?/SPAN>
(2)q行效率Q如果JDBC的代码写的非怼化,那么JDBC架构q行效率最高,但是实际目中,q一点几乎做不到Q这需要程序员非常_NJDBCQ运用Batch语句Q调整PreapredStatement的Batch Size和Fetch Size{参敎ͼ以及在必要的情况下采用结果集cache{等。而一般情况下E序员是做不到这一点的。因此Hibernate架构表现出最快的q行效率。EB的架构效率会差的很远?/SPAN>
(3)开发效率:在有Eclipse、JBuilder{开发工L支持下,对于单的目QEB架构开发效率最高,JDBCơ之QHibernate最差。但是在大的目Q特别是持久层关pL很复杂的情况下QHibernate效率高的惊hQJDBCơ之Q而EB架构很可能会p|?/SPAN>
2 数据持久层设?/FONT>
复杂性是应用开发过E中最令h头疼的一个问题。每当在一个应用中增加一个功能时Q它的复杂性通常呈几何的增ѝ这U复杂性往往DE序的开发无法再l箋下去。这也是现在Z么许多应用只?SPAN lang=EN-US>Beta版本而没有正式版的原因?SPAN style="mso-spacerun: yes">
专家应用开发过E生的复杂性分Zc,即非本质的(accidentalQ和本质的(essentialQ。本质的复杂性是对于解决目标问题所必然产生的复杂性,非本质的复杂性是׃选择了不适当的开发工具和设计工具而生的复杂性。对于一个功能确定的E序来讲Q本质的复杂性是定的,而非本质的复杂性则是没有限制的。因此,一个应用的开发要惌利地取得成功,需要尽可能地减非本质的复杂性?O:P>
设计模式使h们可以更加简单方便地复用成功的设计和体系l构。将已证实的技术表q成设计模式Q也会新系l开发者更加容易理解其设计思\?SPAN lang=EN-US>
衡量一个系l优U与否的关键因素,除了能够满用户需求外q有如下斚wQ首先是灉|性。灵zL意指这U结构或模式不依赖于M实际应用Q应该与操作pȝ、应用程序无兟뀂提供独立的l构Q可以提供最大的重用。其ơ是可扩展性。随着业务的扩展,新的业务不断增加Q业务逻辑自然增加Q系l必然会q行修改或添加相应功能模块。再ơ是可配|性。最后是安全性?SPAN lang=EN-US>
数据持久层的设计采纳了多U设计模式,最大限度的降低了系l内部各模块、子pȝ间的耦合性,使得pȝ相对易于扩展Qƈ且能够在q行改变Ӟ保证持久层的业务逻辑层相对稳定,基本不需要因持久层的调整改变而进行逻辑层的变动?SPAN lang=EN-US>
W者在目中采用了如下设计模式?SPAN lang=EN-US>
2.1 整体架构——MVC模式Q模?视图-控制器)
t 模型QModelQ:模型包含完成d所需要的所有的行ؓ和数据。在数据持久层中Q模型即为值对象以及数据访问对象?O:P>
t 视图QViewQ:数据持久层中Q视囑ְ是持久层同其它层q行数据交换的值对象(Transfer ObjectQ和视图助手对象?O:P>
t 控制器(ControllerQ:持久层所需的控制相对简单,因此集成C控制代理中?O:P>
持久层整体采?SPAN lang=EN-US>MVC模式Q得整个数据持久层的实现部分与目的业务逻辑部分隔离开来,能够实现Ҏ口作大的修改而不需要对相应的模型进行修攏V另外,持久层某子系l发生变化时Q不会媄响到其它子系l。有利于提高pȝ的稳定性、可l护性?/SPAN>
2.2 值对象模式(Value Object PatternQ?/SPAN>
值对象用来封装业务对象。相应的Ҏ调用是设|(getterQ和索(setterQ值对象。它是Q意的可串行化的Java对象Q当客户端Beanh业务数据Ӟ该Bean可以构造值对象,用属性值来填充Qƈ按照值把它传递给客户端?O:P>
在笔者开发项目的数据持久层体pȝ构中Q值对象主要应用在子系l间传递、交换数据(Transfer ObjectQ和映射数据表两个方面(Persistent ObjectQ?O:P>
在各子系l间q行数据传递和数据交换Ӟ使用值对象模式能够最大化地降低系l间数据传递的开销。在q种{略下传递的是对象而不再是一个个的有意义的数据,使得pȝ在进行扩充、修ҎQ各子系l间数据传递部分不会受到媄响,因ؓ各子pȝ仅需要关心是否有值对象被传递,而ƈ不去兛_传递的到底是什么数据?SPAN lang=EN-US>
在映数据库表时Q值对象类及其子类所构成的树形结构被用来映射一个数据库表,该承树通过XML配置文g对应数据库中的单个表Q这使得最底层的关pd的数据库表结构能够面向对象模型所隐藏Q另外,׃面向对象设计Ҏ中类的可l承性,采用l承树对应一个表的策略得该映射{略极易扩展Qƈ且能够将一个复杂的数据表{化成若干单的值对象来表示Q提高了pȝ的可l护性和可修Ҏ?O:P>
2.3 数据讉K对象QDAOQ?/SPAN>
Ҏ数据源不同,数据讉K也不同。根据存储的cd(关系数据库、面向对象数据库{?和供应商不同Q持久性存?比如数据?的访问差别也很大。当业务lg或表C组仉要访问某数据源时Q它们可以用合适的API来获得连接性,以及操作该数据源。但是在q些lg中包含连接性和数据讉K代码会引入这些组件及数据源实C间的紧密耦合。组件中q类代码依赖性应用E序从某U数据源q移到其它种cȝ数据源将变得非常ȝ和困难,当数据源变化Ӟlg也需要改变,以便于能够处理新cd的数据源?O:P>
W者开发项目的数据持久层用数据访问对?SPAN lang=EN-US>(DAO)来抽象和装所有对数据源的讉K。DAO理着与数据源的连接以便于索和存储数据QDAO实现了用来操作数据源的访问机Ӟ内部装了对Hibenernate数据操纵、事务处理、会话管理等API的封装。外界依赖于DAO的业务组件ؓ其客L使用DAO提供了更单的接口QDAO完全向客L隐藏了数据源实现l节。由于当低层数据源实现变化时QDAO向客L提供的接口不会变化,采用该设计模式允许DAO调整C同的存储模式Q而不会媄响其客户端或业务lgQ即使将来不再采用Hibernate作ؓ关系映射框架Q上层客L也不会受CQ何媄响。另外,DAOq充当组件和数据源之间的适配器的角色?O:P>
数据持久层通过调整抽象工厂(Abstract Factory)模式和工厂方?Factory Method) 模式(q二个创建型模式的实现详情参见GoF?lt;设计模式>)Q?QDAO模式辑ֈ了很高的灉|度?O:P>
当底层存储随着实现的变化而变化时Q该{略可以通过使用抽象工厂模式实现。抽象工厂可以基于工厂方法实现而创建,q可使用工厂Ҏ实现。该{略提供一?SPAN lang=EN-US>DAO的抽象工厂对象,其中该对象可以构造多U类型的具体的DAO工厂Q每个工厂支持一U不同类型的持久性存储实现。一旦你获取某特定实现的具体DAO工厂Q可以用它来生成该实现中所支持和实现的DAO?O:P>
2.4 q接池、应用~存及n元模式(提升pȝ性能Q?/SPAN>
t ~存QCacheQ?O:P>
对于数据库来_厂商的做法往往是在内存中开辟相应的区域来存储可能被多次存取?数据和可能被多次执行的语句,以ɘq些数据在下ơ被讉K时不必再ơ提交对DBMS的请求和那些语句在下ơ执行时不必再次~译?O:P>
同样Q数据持久层采用~存技术来保存已经从数据库中检索出来的部分常用数据。客L讉K持久层时Q持久层首先访问缓存,如果能够命中则直接从~存中提取数据,否则再向数据库发送提取数据的指o。这U设计能够大q度地提高数据访问速度?SPAN lang=EN-US>
t q接池(Connection PoolQ?O:P>
池是一个很普遍的概念,和缓冲存储有机制相近的地方,都是~减了访问的环节Q但它更注重于资源的׃n?SPAN lang=EN-US>
对于讉K数据库来_建立q接的代h较昂贵,因此Q数据持久层建立了“连接池”以提高讉K的性能。数据持久层把连接当作对象,整个pȝ启动后,q接池首先徏立若q连接,讉K本来需要与数据库连接的区域Q都改ؓ和池相连Q池临时分配q接供访问用,l果q回后,讉K连接交q。这U设计消除了JDBC与数据源建立q接的gӞ同时在应用提供了对数据源的q发讉K?/SPAN>
t 享元模式QFlyweightQ?O:P>
面向对象语言的原则就是一切都是对象,但是如果真正使用hQ有时对象数可能昑־很庞大,比如Q数据库中的记录Q如果以每条记录作ؓ一个对象,提取几千条记录,对象数就是几千,q无疑相当耗费内存。数据持久层依据享元模式设计了若q元c,装可以被共享的cR这U设计策略显著降低了pȝ的内存消耗?SPAN lang=EN-US>
2.5 各种对象的创建模?/SPAN>?/SPAN>工厂ҎQ?SPAN lang=EN-US>Factory MethodQ?/SPAN>
工厂Ҏ模式创建实例的工作与用实例的工作分开Q也是_让创建实例所需要的大量初始化工作从单的构造函C分离出去。只需要调用一个统一的方法,卛_Ҏ需要创建出各种对象的实例,对象的创建方法不再用~码到程序模块中Q而是l一~写在工厂类中。这样在pȝq行扩充修改Ӟpȝ的变化仅存在于工厂类内部Q而绝对不会对其他对象造成影响?/SPAN>
Q收E日期:2004-12-31 EmailQ?A href="mailto:chl@tsxd.sina.net">chl@tsxd.sina.netQ?/FONT>