本文想将我的一些开发维护心得与问题得与大家分享,也许文中的内容你已经遇到过,并解决了,但可以当时并没有想为什么要这么做?要分享的内容还是围绕经典的webwork,
spring
,
Hibernate
,没办法绝大多数做
Java
的人还得靠这几个吃饭.开始吧.
Hibernate
部分
Hibernate
是这三个框架最好入门,但最难掌握的.用不好,随随便便一个请求,就查询几百条
SQL
语句是很容易发生的.这样我们通过分析生成出来的
SQL
语句,看看哪里有优化的必要.
场景一:
考虑以下
Pojo
实体之间的联系:
World
一对多
Country
一对多
Province
一对多
City
这样就形成了一棵树.每一个
World
实体是树的根部,
City
是叶子结点.
好,我现在将所有实体的一对多配置中配置
lazy=”false”
,例如
在
World.java
中配置:
<bag name="countrys" lazy="false" cascade="all">
<key column="fk_world_id" />
<one-to-many class="com.leo.domain.query.Country" />
</bag>
其它关联配置类似,现在我要查询
World
实体,代价是非常大的.
比如说:
List<World> lists =
session
.createQuery(
"from
World"
).list();
<!---->1.
<!---->发送一条
SQL
语句取出所有
World
:
select
*
from
tbl_world
<!---->2.
<!---->根据上面的查询结果,分别发送一条语句得到每个
World
所持有的
Country
对象:
select * from tbl_country where
fk_world_id=?
select * from tbl_country where
fk_world_id=?
...省略
<!---->3.
<!---->接下的查询重复上面的步骤,直接最后的叶子结点.
如果记录很多,你可以欣赏到像骇客帝国那样的
SQL
语句刷屏效果了.不要以为这样的情况很少见,几张表关联在稍微复杂一点的业务逻辑上就能反映出来,我上面是为了描述清楚所以举了一个简单的例子,如果直接将系统代码关系弄出来,估计大家也没耐心看蜘蛛网了.
你也许马上会说,干吗不让
lazy=”true”
,这样只会执行一条语句.没错!
那是因为我现在只是单独的把
Hibernate
部分抽出来看了,因为他们无法解决当
lazy=”true”
后的更多问题,所以,只好设置
lazy=”false”
一了百了,肯定不出错,但性能其差.
解决办法
:
<!---->1.
<!---->打断关联,即去掉
<
bag
name
=
"countrys"
lazy
=
"false"
cascade
=
"all"
>
部分,如果这些要关联的表不经常用来显示,查询,那么这一招不错.
<!---->2.
<!---->设置
lazy=
”
true
”,但会出现很多新的问题,待会我在
Spring
部分会提到.
心得:
在使用一多对时,要慎重考虑关联的跨度,间接关联也是关联,尤其在当只能
lazy=”false”
的场合下,一定要考虑是直接取消一对多.这样情况,就算用缓存,代价也是相当大的.
场景二:
注意此问题在
Hibernate+Spring
中才会出现,如果只是单纯的
Web framework+Hibernate
不会出现此问题.如果你开启了
OpenSessionInViewFilter
模式,那么在编写代码时,容易出现很多问题.下面是我发现的一个问题,首先不知出于什么原因,我们底层的
dao
在封装
delete
方法时出现不同的版本
:
版本一
public void delete(Object obj) throws DAOException {
hibernateTemplate.delete(obj);
}
版本二
public void deleteByKey(final Class cls, final String key,
final String value) throws DAOException {
hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
String deleteClassName = cls.toString().substring(
cls.toString().lastIndexOf(".") + 1);
Transaction tx = session.beginTransaction();
int deletedEntities = session.createQuery(
"delete " + deleteClassName + " where " + key + "='"
+ value + "'").executeUpdate();
tx.commit();
session.close();
return null;
}
});
}
本质上没有多大区别,一个是直接采用
Spring
的
HibernateTemplate
,另一个是采用
Spring
的
hibernateTemplate.execute()
方法来回调,但是请注意,我们在回调代码里既有
tx.commit()
操作,又有
session.close()
操作,
这对于使用了
OpenSessionInViewFilter
模式来说,就会出问题.
来看一段错误的调用代码吧:
假设以下代码封装某个
Service
的
txSave()
方法中,并且我已经在
Spring
的
applicationContext.xml
配置了,
tx*
为前缀的方法都需要事务支持.
//功能,先删除所有记录
dao.deleteByKey(UserInfo.class, "userId", "superleo");
//根据页面选择的checkbox,循环生成一次
for(int i=0; i<list.size(); i++){
UserInfo info = new UserInfo();
info.setUserId(userId);
...
dao.save(info);
}
这样执行时,会报
Hibernate Session
的事务启动不成功,原因就是咱们上面的
deleteByKey()
方法将原本由
Spring
的
OpenSessionInViewFilter
来提交的事务以及要关闭的
Session
自作主张的由我们来做了
.
解决办法
:
直接采用
hibernateTemplate
来删除,比如说现在改成:
List userInfos = dao.find("from UserInfo info where info.userId = ?"
, parameters);
int size = userInfos.size();
for (int i = size - 1; i >= 0; i--) {
dao.delete(conRoles.get(i));
}
其它
Hibernate
问题:
这个问题发生时,我开始很困惑,一开始明明是好好的,只是将
<
bag
name
=
"**"
lazy
=
"false"
cascade
=
"all"
>
改成了
<
bag
name
=
"**"
lazy
=
"true"
cascade
=
"all"
>
就出问题了.
如果你遇到了类似的问题,请先不要急着改代码,上述配置文件改成
<
bag
name
=
"**"
lazy
=
"true"
cascade
=
"delete-orphan"
>
或
<
bag
name
=
"**"
lazy
=
"true"
cascade
=
"none"
>
试试.
- <!---->
<!---->Hibernate
实体应该是细粒度的吗?
对于这个问题,我一直深信不疑,但在实际开发中,你会发现大量的冗余字段,而这些冗余字段的初衷可能仅仅是因为不愿意建
“双向关联”
.
上面我们已经看到“一对多”如果滥用存在很多问题,但反过来“多对一
”却是一个非常好的最佳实践,对
Hibernate
来说,先看下面代码:
user.getGroup()
或
user.getGroup().getId()
上面不会实际上立即发送一条
sql
取出
group
来
(
当然可以配置成
eager fetch
的
)
,而且这种情况用的还真不少.
而现在我们的
User
实体却是下面这种情况:
User.class
下有
groupName, groupId
departmentName, departmentId
.....
当
Group
实体的
name
属性改变时,
User
的
groupName
属性非常可能被忽略掉,从而信息更新不及时.
departmentName
同理也是如此,如果到处都是这样的设计的话,你就祈祷用户永远不要改组名或部门名称吧.
- <!---->
<!---->Hibernate
的
get()
和
load()
方法.看到这里,请不要误会,我不是想说
get
和
load
的区别,但如果知道
get
和
load
区别的开发人员,似乎心里都感觉
load
比
get
好,因为
Hibernat
Session
缓存起了作用.但其实不是这样的,
load()
有时候就像一块毒瘤,因为如果记录不存时,他会抛出可恶的异常.所以,有人即想享受
Hibernat Session
缓存,又想摆平
load()
异常,于是有了下面的“妙笔”:
Object o = null;
try{
o = hibernateTemplate.load(cls, id);
}catch(Exception e){
o = null;
}
return o;
其实简简单单一句:
return
hibernateTemplate
.get(cls, id);
就可以搞定的问题,弄得如此复杂,要记住:异常本身也会造成性能下降.所以,在
Web
实际开发过程中,极力推荐使用
get
.
- <!---->
关于使用
Hibernate
缓存.
使用
Hibernate
缓存很容易使用,如果系统可以使用的话,尽可能的使用.但遗憾的是,我们系统要求任何操作都要反应出最新值来,而且有频繁的插入,删除操作,在使用缓存时,记录无法即时的反应出来,总要间隔一个时间段,才能正确的同步显示在页面上.我打算如用上线一段时间,各项都基础信息都相对稳定时,可以考虑再次使用缓存.
- <!---->
<!---->如何管理
Hibernate
的
*.hbm.xml
文件
一般人都喜欢直接打开后,手工编写或修改,这样做最快最直接.我早期开发
Hibernate
的时候,也一直这么做.但现在似乎不行:实体已经快
100
个了.维护期间数据库新增加字段频繁,时间一长,手工编写不仅又慢又枯燥,还容易出问题.这样有两个比较好的解决办法:
<!---->1.
<!---->使用
Ant +
XDoclet
<!---->2.
<!---->使用
Hibernate
Annoation
实体越多,表越多,关联越多,优势都明显;毕竟同时维护代码和
*.hbm.xml
真的辛苦还不讨好,映射弄错了,马上就有人抱怨了.
接下来的
Spring,Webwork
部分正在编写中.
分享到:
相关推荐
在Java EE企业应用开发中,"轻量级"一词通常指的是使用不那么复杂、资源占用较少的技术栈来构建高效且可维护的系统。在这个实战教程中,作者李刚聚焦于Struts 2、Spring和Hibernate这三个核心组件的整合,它们是Java...
《轻量级Java EE企业应用实战——Struts 2+Spring+Hibernate整合开发电子书1》是一本专注于Java EE企业级应用开发的书籍,主要涵盖了Struts 2、Spring和Hibernate这三个流行开源框架的整合应用。这本书对于Java...
总之,“Struts2+Spring+Hibernate框架技术与项目实战”涵盖了Web开发中的许多核心技能,学习和掌握这一套技术栈,对于提升Java开发者的专业素养和解决实际问题的能力有着显著的帮助。通过不断实践和深入理解,...
在本资源中,我们关注的是"轻量级J2EE企业应用实战——Struts+Spring+Hibernate整合开发"的源码第五部分。这个主题涉及到Java企业级应用开发中的三个核心框架:Struts、Spring和Hibernate的集成使用。下面将详细阐述...
《轻量级Java EE企业应用实战——Struts 2+Spring+Hibernate整合开发电子书3》是一本专注于Java EE轻量级开发技术的专著,它深入探讨了Struts 2、Spring和Hibernate(SSH)这三大流行开源框架的集成与应用。...
《轻量级Java EE企业应用实战——Struts 2+Spring+Hibernate整合开发》是一本深入探讨Java EE企业级应用开发的书籍,尤其关注于轻量级框架的整合使用。Struts 2、Spring和Hibernate,简称SSH,是Java开发中最流行...
通过学习《轻量级Java EE企业应用开发实战———Struts 2+Spring+Hibernate整合开发》这本书籍和配套的课件,开发者可以深入理解 SSM 框架的原理和实践,掌握企业级应用开发的关键技能。课程中可能涵盖了如何搭建...
这些都是在实际开发中经常遇到的技术难点,通过本书的学习,读者可以掌握解决这些问题的方法和技巧。 #### Hibernate in Spring “Hibernate in Spring”章节讨论了如何将Hibernate集成到Spring框架中,实现更高效...
【标题】"轻量级J2EE企业应用实战——Struts+Spring+Hibernate整合开发 源码第一部分"指的是一个教程或者项目实践,旨在帮助开发者掌握如何在J2EE环境中整合三大主流开源框架:Struts、Spring和Hibernate。...
在《轻量级 J2EE 企业应用实战:Struts+Spring+Hibernate 整合开发》这本书中,读者可以期待学习到如何配置和使用这三个框架,理解它们之间的协作方式,以及如何在实际项目中有效地应用SSH架构。书中可能涵盖从基本...
《轻量级Java_EE企业应用实战_Struts_2+Spring_3+Hibernate整合开发_第3版》这本书深入探讨了在Java EE环境下如何利用轻量级框架Struts 2、Spring 3和Hibernate进行高效的企业级应用开发。这三者结合在一起,形成了...
在本章中,我们将深入探讨Java Web开发中的一个经典整合框架——Struts 2、Hibernate和Spring的联合应用。这三位技术大师贾蓓、镇明敏和杜磊为我们提供了宝贵的实战经验,帮助开发者理解如何有效地将这三个框架集成...
《Dwr2+Struts2+Spring2.5+Hibernate3实战——用户登录注册系统》这篇文章探讨了如何利用四个主流的Java开发框架构建一个用户登录注册系统。Dwr2、Struts2、Spring2.5和Hibernate3各自扮演着关键的角色,共同实现了...
【轻量级Java_EE企业应用实战_Struts2_Spring3_Hibernate整合开发】这个主题主要涉及的是Java EE领域中的三大框架——Struts2、Spring3和Hibernate的集成应用,这是构建现代Java后端系统的一种常见方式。这些框架...
《Hibernate框架开发2016版视频资料》是由知名教育机构黑马程序员与传智播客联合推出的培训课程,旨在帮助学员深入理解并掌握Java领域中备受推崇的对象关系映射(ORM)框架——Hibernate。该课程内容详实,适合对...
通过阅读这本书,读者不仅可以掌握三大框架的基本用法,还能了解到实际项目开发中的最佳实践和常见问题解决方案。 总而言之,《Spring+Struts+Hibernate整合开发》是一本面向实战的指南,它将带领读者深入了解Java ...
《疯狂JAVA实战演义——源码》是一本深入解析JAVA编程实践的书籍,作者通过精心设计的15个实际应用开发案例,旨在帮助读者逐步掌握JAVA编程的核心技能,并提升其在实际开发中的应用能力。书中的每个实例都包含了完整...
Struts+Spring+Hibernate整合开发是Java Web开发中常见的技术栈,被称为SSH框架。这个框架组合提供了模型-视图-控制器(MVC)架构模式的支持,使得开发人员能够更高效地构建可维护、可扩展的企业级应用。在这个"轻量...
6.1 案例分析:结合黑马程序员的day1至day4的讲义和笔记,深入理解在实际项目中如何应用Hibernate,解决具体问题。 总结,Hibernate作为强大的ORM框架,为Java开发者提供了便利,通过理解并熟练掌握其核心概念、...