Hibernate和spring开发web应用时要注意的几个环节

本文详细探讨了Spring框架与Hibernate ORM技术的整合应用,重点介绍了getHibernateTemplate、getCurrentSession及getSession的不同应用场景,并深入分析了事务管理策略及DAO层的设计原则。

     近期在用hibernate和sping开发web应用时遇到一些问题,比较详细的阅读了一下相关文档(主要是《轻量级J2EE企业应用实战》和《spring recipe》以及《实战hibernate》),搞清了几个方面的差别,简单地记录一下。日后在做其他项目时可以作为项目组内预先做好技术准备的内容。

     spring提供的getHibernateTemplate和getSesstionFactory().getCurrentSession()以及getSession()的区别。getHibernateTemplate是由spring控制session的开启和关闭,不需要由开发者介入,只要在配置文件中配置好来管理的transactionManager即可。纯粹的读取操作都可以使用这个方法来实现,设定参数等都有多种重载方法提供出来,基本可以满足需求。如果有需要对hql进行比较详细的定制,例如运行sql语句,进行无关联表的join操作(这种情况多出现在针对老的数据库开发程序而又无权对数据库表结构进行变更的情况),需要addEntity(), addScalar()等,getHibernateTemplate提供了callback的方法,仍然可以将其置于其管理之中。

     对比getSession(),如果忘记调用close()的话,在web应用中很快就会给你颜色看,调用个几次这个方法程序就会挂在那里没有反应了。这时候需要排查什么地方调用了getSession()而忘记了close()。与其这样不如用上面的方法来的省心可靠。

     如果逻辑牵涉到读取以外的更新,插入,删除的操作,如果这些操作独立存在彼此没有联系,我们仍然可以使用getHibernateTemplate来进行操作。但如果这几样操作有某种联系,一个操作失败其他的数据也不能更新,也就是保持数据的acid特性,这就需要用到事务的控制。事务一定是指几个对数据库的操作(包括更新,插入,删除操作)捆绑在一起的组合,要么一起成功要么一起失败。这时getSessionFactory().getCurrentSession()就派上用场了,如果没有在事务中被调用是会抛出提示性的错误,告诉你这个方法必须在事务中被调用。

     以上是这三种方法使用的大致场景,再具体说一下事务。具体来讲DAO这一层不应该定义事务,应该在service这一层来定义。DAO层定义的都是最小的对数据库的操作,单一的操作谈不上事务。为何会这样说?这是因为还牵涉到另外一个问题,是在看spring recipe这本书的时候,提到一个定义了事务的方法在被另一个定义了事务的方法调用时会有的问题。我一上来想当然的觉得应该是DAO上的方法被放在一起被service调用,这是错误的。实际上应该是service这一层或者更上一层的事务相互调用。

     定义了事务的方法相互调用,他们的关系在spring里主要的有两种,一种是默认的required还有一种是require new。spring recipe书里举的例子很好,这里简单解释一下required,一个定义了事务的方法A和另一个定了事务的方法B,B调用A,调用开始,B的事务开始,调用A时,A使用B的事务,A结束后,B做完自己的事后事务结束。而require new则是在B调用A,B事务开始,B调用A时,B的事务挂起,A开始自己的事务,A事务结束后,B的事务恢复,完成后B事务结束。这些是很细微的差别,具体说明请看spring的文档。

     另外,应当尽量使用hql,如果数据库可以根据hibernate的规范进行修改或创建,那么整个DAO应该说用hql是足够了。只有数据库无法修改,那只能使用hql和sql混合的方式来编写DAO,这是无奈之举并不提倡。hql和sql在hibernate中被调用的区别有如下几点:

     由于hibernate完整的映射了数据库的表结构,包括1-n,n-1等等关系,在写hql的时候,join的方法和sql基本一致,区别是join右边的表需要指明路径。例如join左边的表别名是p,那么它关联的表需要写成p.xxx,否则会抛出异常提醒路径不对。

     如果在hibernate中使用常规sql则需要指明将结果映射到什么具体的类,用addEntity(xxx.class)来指明,有时会遇到类型不一致,还要制定具体的类型,比较麻烦。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     此外,如果使用annotation的方式来配置项目的话,可以简单注明<context:annotation-config />,这样就可以用@Autowired来引用bean了。自动装配bean默认是按照类型,如果此类型的实例有多个则不能工作,需要用@Qualifier来标明bean的名称。

     声明bean同样可以使用annotation的方式,按照分工可以分为@Repository,@Service,@Controller。它们分别代表DAO层,服务层,和控制器层。如不分类的话可统称为@Component。具体如下:

      <context:component-scan base-package="com.apress" >
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>

    base-package可以用逗号分隔,type可以有四种类型,annotation和assignable用来描述标注类型和类/接口,regex和aspectj用来描述正则表达式和aspectj的表达式。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     页面开发会用到标签库,除了jstl标签库外,还会为自身需要定制自定义标签库。这里提供了SimpleTagSuppor类,继承这个类后,标签类包含的属性都要有对应的getter和setter方法,另外就是要重写doTag()方法,这个方法负责生成页面内容。定义的tld格式如下:

     <tag>
        <name>checkowner</name>
        <tag-class>com.apress.component.tag.CheckOwner</tag-class>
        <body-content>scriptless</body-content>       
        <attribute>
            <name>userId</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

     另外还会用到表达式语言EL,其中表达式语言还可以自定义函数,开发步骤非常类似于标签开发。自定义函数就是普通类,包含若干个静态方法,每个静态方法都可以定义成一个函数。例子如下:

     <function>   
        <description>format Timestamp to be yyyy-mm-dd</description>   
        <name>fmtTimeStamp2Date</name>   
        <function-class>com.apress.util.QfmFunctions</function-class>   
        <function-signature>   
            java.lang.String fmtTimeStamp2Date(java.sql.Timestamp)   
        </function-signature>   
        <example>${qfnc:fmtTimeStamp2Date(str)}</example>
    </function>

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值