《深入浅出Hibernate》缓存,实体生命周期,事务处理

来源:互联网 发布:扮猪吃老虎 网文 知乎 编辑:程序博客网 时间:2024/04/28 16:51

已读到《Hibernate高级特性》一章,看china-pub和第2书店上的书评,都说这才是本书的精华所在,仔细研读中。。。概念开始比较多了,也澄清了一些过去模模糊糊的概念,比如实体对象的3种状态,比如PO,VO之争,比如Hibernate的二级缓存是怎么回事。全章分为两部分,第一部分Hibernate的持久化操作,包括以下内容:

  1. 实体对象的生命周期。在Hibernate中,实体对象只能为3种状态:Transient,Persistent,Detached。Transient即实体对象是自由的,与数据库中的记录无关。Persistent即实体对象处于Hibernate框架的管理之中,其变更将由hibernate更新到数据库中。Detached(游离),处于Persistent状态的对象在Session关闭之后,此对象就处于Detached状态。比如:
                    TUser user=new TUser();    
                    user.setName("dennis");   //user此时为Transient状态        
                    Transaction tran=session.beginTransaction();

                              session.save(user);           //user开始处于Persistent状态           
                              tx.commint();

                              session.close();             //session关闭之后,user处于detached状态

               那么,Detached状态与Transient状态的区别在哪?区别就在于Detached可以再次与session相关联而进 入Persistent状态。Transient的对象与数据库记录缺乏联系,比如没有主键,而Detached对象是与数据库的记录相联系的,在库中有相应的记录(通过主键唯一确定)。我们可以人工制造Detached对象。由此可引出VO和PO的概念,我们从“实体是否纳入Hibernate实体管理器的管理的”的观点出发,把非管理的实体对象(Transient,Detached)称为VO(Value Object),把被管理的实体对象称为PO(Persistence Object)。由PO和VO的概念引出一个设计上的考量,如在传统的MVC架构中,PO是否被允许传播到其他层,因为PO的更新将最终被影射到数据库,所以如果PO在其他层遭到了变动,可能对Model层造成意想不到的破坏,一般是通过构造一个DTO对象来避免此情况(尽管这被rod狂批了一顿)。此方面的技术有commons项目的BeanUtils和dozer.

         2.实体对象的识别:此节主要讨论了如何撰写实体对象的equals()和hashCode()方法。从两种角度出发,站在数据库的角度,我们应该认为在一库表结构中,主键可以唯一确定一条记录,那么,拥有同样主键值的对象,则认为他们等同。而从业务逻辑的角度出发,我们可能认为一个user对象的name相同,就认为此两个实体对象等价,需要根据特定领域中的逻辑规则。值对比,即在equals/hashcode方法中,对实体类的所有属性的值进行对比,只需针对实体类的属性进行处理,而不要涉及实体类所关联的集合类的对比。Hibernate中的脏数据检查是通过数据版本比对机制,书中给出了一个对象更新过程的UML序列图。

         3。数据缓存。在ORM中,缓存一般分为3个层次:                 
                A。事务级缓存,当前事务范围内的缓存策略

                B。应用级,在某个应用中,或者应用中某个独立访问数据库的子集中的共享缓存。

                C。分布式缓存,在不同JVM中共享的缓存模式。

             Hibernate中的缓存分为两个层次:

              A。Session Level,内部缓存,通过session在内部维持一个Map数据类型维护当前Session中的所有有关PO的状态。通常情况下由Hibernate自动维护,可通过Session.evict和Session.clear人工管理。

              B。SessionFactory Level,二级缓存。涵盖了应用级和分布式缓存。二级缓存将由从属于本SessionFactory的所有Session实例共享。关于2级缓存的具体讨论,在javaeye上有个很精彩的帖子。http://forum.javaeye.com/viewtopic.php?t=18904

         4。事务管理。首先介绍了概念,如ACID,事务管理隔离等级等。再解释了Hibernate中的两种事务管理类型:JDBC和JTA。在实际应用中可能更多的与spring集合,采用spring封装的事务管理。如配置:

        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!--Base TransactionProxyed Service Bean-->
    <bean id="baseTxService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="proxyTargetClass" value="true"/>

        <property name="transactionAttributes">
            <props>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
                <prop key="remove*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
        <property name="preInterceptors">
            <list>
                <ref bean="methodSecurityInterceptor"/>
            </list>
        </property>
    </bean>

要纳入事务管理的bean,只要如此声明:


    <bean id="bookManager" parent="baseTxService">
        <property name="target">
            <bean class="org.springside.bookstore.service.logic.BookManager"/>
        </property>
    </bean>

以上片段摘自SpringSide项目。

Hibernate支持两种锁机制,即通常所说的“悲观锁”与“乐观锁”。

A。悲观锁,指的是对数据被外界修改持保守态度,在整个数据处理过程中,把数据一直维持在锁定状态。一般都是通过调用数据库的锁机制实现,典型代码如下:

String hqlstr="from TUser as user where user.name='dennis'";

Query query=session.createQuery(hqlstr);

Query.setLockModel("user",LockModel.UPGRADE);      //此句实现了加锁

List list=Query.list();    //执行查询。

常见锁机制:LockModel.UPGRADE,LockModel.UPGRADE_NOWAIT(仅限oracle)。加锁可通过Criteria,Session,Query的setLockModel方法实现。

B。乐观锁。悲观锁在大多数情况下依赖数据库的锁机制,保证最大限度的独占性,但对于长事务而言,随之而来的是数据库性能的大量开销。因此才有了乐观锁,与悲观锁不同,乐观锁其实并未给数据加锁,它是通过数据版本记录机制实现,只有提交的数据版号大于数据表当前数据版本号,才给予更新,否则认为是过期数据。一般是为数据库表增加一个"version"字段。配置如:

<class name="TUser" table="t_user" optimistic-lock="version">

<version column="version" name="version" type="java.lang.Integer"/>

optimistic-lock的值可以为:none,version,dirty,all。官方推荐version实现的乐观锁机制。

 

原创粉丝点击