`
neeleon
  • 浏览: 186078 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

hibernate入门(十一)事务

阅读更多

1.事务引发的三层架构MVC讨论:
在前面的程序代码中多次用到了事务:
Transaction tx = s.beginTransaction(); 
             对应的jdbc代码:connection. setAutoCommit(false);
.....
.....数据处理
.....
tx.commit();
                对应的jdbc代码:connection.commit();   
tx.rollback();
对应的jdbc代码:connection.rollback();   
以上的三处事务相关的代码统称为“事务边界”。其实hibernate的事务本质是依赖jdbc的事务来实现,其实对于事务而言,它是应该由业务逻辑层来实现,但是事务所依赖的对象又出现在Model层,所以想严格按照MVC的原理来实现将相当难(在前面我们所写的代码中事务的处理是不符合mvc模式得),但是利用推出的EJB,SPRING这些框架将能达到此目的,下图展示了三层架构,与原始的MVC相比,多了一个持久层。


 
2.模拟session context[OSIV]:
>>步骤一,重写工具类,核心代码如下:
package com.asm.hibernate.utils;
public class HibernateUtilOSV {
    private static SessionFactory sf;
    private static ThreadLocal session = new ThreadLocal();
    private HibernateUtilOSV() {
    }
    public static Session getThreadLocalSession() {
        Session s = (Session) session.get();
        if (s == null) {
            s = getSession();
            session.set(s);
        }
        return s;
    }
    public static void closeSession() {
        Session s = (Session) session.get();
        if (s != null) {
            s.close();
            session.set(null);
        }
    }
    static {
        Configuration cf = new Configuration();
        cf.configure();
        sf = cf.buildSessionFactory();
    }
    public static SessionFactory getSessionFactory() {
        return sf;
    }
    public static Session getSession() {
        return sf.openSession();
    }
}
>>步骤二、导入servlet包,使用Filter. 内容如下:
package com.asm.hibernate.osv;
public class OpenSessionViewFilter implements Filter {
    public void destroy() {
        // TODO Auto-generated method stub
    }
    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain arg2) throws IOException, ServletException {
        Session s = null;
        Transaction tx = null;
        try {
            s = HibernateUtilOSV.getThreadLocalSession();
            tx = s.beginTransaction();

            arg2.doFilter(arg0, arg1);
            tx.commit();
        } catch (Exception e) {
            if (tx != null)
                tx.rollback();
        } finally {
            HibernateUtilOSV.closeSession();
        }
    }
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
    }
}
>>步骤三、Userdao:
package com.asm.hibernate.osv;
public class UserDao {
    static void addUseDao(User user) {
        HibernateUtilOSV.getThreadLocalSession().save(user);
    }
}
原理流程分析:当有被Filter监测的请求到达此Filter时,Filter会利用工具类来获得一个Session,并用这个session打开事务,然后再把请求传给下一个Filter.当所有操作执行完成后再返回到这个Filter,如果没有任何异常便可以提交事务,否则回滚事务。这样便可以有效保证事务的完整性,而且有利于懒加载,因为在整个请求的过程中,Session一直未关闭,所以在filter不断向下传递的过程中可以放心的使用session来完成懒加载,这也是解决懒加载的一种方式。其实OpenSessionInView主要解决了两个问题:一是实现事务在逻辑层控制,二是利于懒加载的实现。 下面再来看看工具类:此工具类主要完成了两个工作:一是生成一个线程级的Session,即是说在一个线程的事务开启到事务结束,一直用的是同一个Session,这样有利于保证事务的完整性,而工具类主要借助了ThradLocal来生成这个线程级的Session。 二是完成Session的关闭。
3.使用Hibernate自带的SessionContext
>>步骤一、在主配置文件中增加如下内容:       
<property name="current_session_context_class">thread</property>以支持事务边界。 说明:它实质也是利用ThreadLocal来管理Session实现多个操作共享一个Session,避免反复获取Session,并控制事务边界。需要注意的是,当我们打开此功能后再通过SessionFactory.getCurrentSession()来获取一个Session,这个Session不能调用close方法,因为当我们提交事务或者回滚事务都会引起这个Session关闭,而通常的事务最会被提交或回滚,所以我们永远不要在这样的Session中调用close方法。同样的它的一个重要作用就是在生成页面时保持Session打开(即OpenSessionInView),因此为懒加载提供了方便。 除了配置为thread外还可以配置值为“jta” ,配置成jta后主要JTA事务管理器来管理事务,jta事务管理器主要用在有多个数据库的情况
>>步骤二、重写工具类:核心代码如下:
package com.asm.hibernate.utils;
public class HibernateUtilSelf {
    private static SessionFactory sf;
    private HibernateUtilSelf() {
    }
    public static Session getThreadLocalSession() {
        Session s = sf.getCurrentSession();
        if (s == null) {
            s = getSession();
        }
        return s;
    }
    static {
        Configuration cf = new Configuration();
        cf.configure();
        sf = cf.buildSessionFactory();
    }
    public static SessionFactory getSessionFactory() {
        return sf;
    }
    public static Session getSession() {
        return sf.openSession();
    }   
}
>>编写测试类:
package com.asm.hibernate.osv;
public class UserTest {
    public static void main(String[] args) {
        User user = new User();
        user.setName("richie");
        user.setDate(new Date());
        addUser(user);
    }
    static void addUser(User user) {
        Session s = null;
        Transaction ts = null;
        try {
            s = HibernateUtilSelf.getThreadLocalSession();
            ts = s.beginTransaction();
            s.save(user);
            ts.commit();
        } catch (HibernateException e) {
            if (ts != null)
                ts.rollback();
            throw e;
        } finally {
            if (s != null)
                // s.close(); //注意这里不能使用close,并注意下面的打印结果
                System.out.println("s=" + s);
        }
    }
}
执行后的结果为:s=SessionImpl(<closed>)
4.悲观锁:
悲观地认为每个事务在操纵数据时,肯定会有其它的事务同时访问该数据资源,当前事务为防止自身受到影响,先将相关数据资源锁定,直到事务结束后释放锁定。
实现方式一:利用LockMode实现数据锁;原理是使用带有LockMode参数的load方法来实现数据加锁,LockMode主要有以下几种锁定方式:
锁定方式    功能
LockMode.NONE    Hibernate的默认值,首先到缓存中检索,检测不到时连数据库
LockMode.READ    不管缓存,直接到数据库中加载。如果在实体配置文件中配置了版本元素,则比较缓存中的版本与数据库中的版本是否一致
LockMode.UPGRADE    在READ的基础上,如果数据库支持悲观锁,则执行select...for update,否则执行变通的select语句。
UPGRADE_NOWAIT    主要是针对Oracle数据库,在UPGRADE的基础上,如果执行select语句不能获得锁,则会抛出锁定异常
实现方式二、通过逻辑实现锁定数据;原理是在实体类的数据库表中设定一个boolean的字段,当这个字段为true,表示该数据正在被访问,此时记录被锁定。如果为false,则表示可以访问。 过程:(1)当访问的数据为false时,表示可以访问,此时修改字段为true,以避免其它对象访问,操作完成后再设此字段为false,以让等待的对象访问 (2)当访问数据据为true,表示不可被访问。
5.乐观锁:
乐观地认为每个事务在操纵数据时,很少有或者不会其它事务同时访问数据资源,因而不会在数据库层锁定,而是通过逻辑来实现版本控制。
实现方式一:<version>方式:为了方便操作新建一个名为OptimizeLock的项目.
>>步骤一,拷贝以前的User类及相应的实体配置文件等相关文件。
>>步骤二,在User类中增加private int version;及相应的get/set方法。Version名字可以随意取。
>>步骤三、修改配置文件:增加<version name="version"></version>属性,并注意在<class>元素中使用optimistic-lock="version"属性,这也是官方推荐使用的属性值。但不能使用none,因为它不支持乐观锁,也可这样说,即使我们为乐观锁做好了一切准备,但我们不想在某个实体对象中使用时,只需要配置optimistic-lock为none即可。
>>步骤四、编写测试类
package com.asm.hibernate.test;
public class VersionUserTest {
    public static void main(String[] args) {
        addUser();
        update(1);
    }
    static void update(int id) {
        Session s1 = null;
        Session s2 = null;
        Transaction tx1 = null;
        Transaction tx2 = null;
        try {
            s1 = HibernateUtil.getSession();
            tx1 = s1.beginTransaction();
            User user1 = (User) s1.get(User.class, id);
            System.out.println(user1.getName());
            s2 = HibernateUtil.getSession();
            tx2 = s2.beginTransaction();
            User user2 = (User) s2.get(User.class, id);

            user1.setName("user1Name");
            user2.setName("user2Name");

            tx1.commit();
            tx2.commit();
        } catch (HibernateException e) {
            ....
        } finally {
            ....
        }
    }
    static void addUser() {
        ...主要作用是增加一条记录以实现操作。
    }
}
分析:在进行分析前,先提下笔者曾范的一个测试错误,由于是复制以前的代码,由于以前在User的配置文件中配置了二级缓存的“<cache usage="read-only"/>” ,这样执行时总是报“Can't write to a readonly object” 。由这点大家可以再细想下悲观锁的更多细节问题。下面来谈version,当我们向数据表中添加一个version字段,hibernate会控制此字段,当访问一条记录时,同时访问此记录的版本信息,如果对该记录做了修改,在提交事务时,hibernate会将访问时的版本信息与数据库中的版本信息进行对比,如果一致则提交修改并将原版本信息加1,否则撤销本次修改。 上面的两个session并分别有开启了两个事务,当提交第一个事务时,符合要求进行了提交。但我们再来提交第二个事务时,由于第一个事务修改了版本信息,尽管user1和user2最初获得的版本是一样得,但由于第一个事务提交修改了数据库中版本信息,所以第二个事务将不能被提交(如不能明白,请仔细阅读本段中的黑体字部份)。  请这样测试:执行完后(会报“Transaction not successfully started”异常)查数据表,然后再交换以上两个事务提交的顺序再执行,再查数据表。 另请不要深究异常处理。
实现方式二、<timestamp>
基本和方式一相同,只是在User类中增加一个Date类型的属性,同时在实体配置文件配置如下内容: <timestamp name="实体类的中Date类型的属性"></timestamp>

  • 大小: 48.4 KB
分享到:
评论

相关推荐

    Hibernate入门到精通

    "Hibernate入门到精通" Hibernate 是一个基于Java的ORM(Object-Relational Mapping,对象关系映射)框架,它提供了一种简洁高效的方式来访问和操作关系数据库。下面是 Hibernate 的主要知识点: Hibernate 简介 ...

    Hibernate入门jar包

    本压缩包提供的是Hibernate入门所需的jar包,包括了Hibernate的核心库以及与之配合使用的相关组件。让我们深入探讨一下这些jar包以及它们在Hibernate中的作用。 1. Hibernate核心库: - `hibernate-core.jar`:这...

    Hibernate入门案例源码

    【Hibernate入门案例源码】是针对初学者设计的一份教程,旨在帮助理解并掌握Java持久化框架Hibernate的基础应用。Hibernate是一个强大的ORM(对象关系映射)框架,它简化了数据库与Java对象之间的交互,使开发者可以...

    初学hibernate,hibernate入门

    **初学Hibernate,Hibernate入门** Hibernate是一个开源的对象关系映射(ORM)框架,它为Java开发者提供了方便的数据持久化服务。在Java应用中,通过Hibernate,开发者可以将数据库操作抽象成对象模型,使得代码...

    hibernate入门小例子

    【hibernate入门小例子】是一个适合初学者的教程,主要涵盖了如何在JavaWeb项目中使用Hibernate框架与MySQL数据库进行集成。在这个例子中,我们将会深入理解Hibernate的核心概念,包括实体映射、对象关系映射(ORM)...

    Hibernate入门

    ### Hibernate入门知识点详解 #### Hibernate概述与ORM思想 - **定义**:Hibernate是一个开源的、轻量级的对象关系映射(Object-Relational Mapping,简称ORM)框架,它主要应用于JavaEE架构中的DAO(Data Access ...

    hibernate入门--第一个实例

    【hibernate入门--第一个实例】 Hibernate 是一个强大的对象关系映射(ORM)框架,它为Java开发者提供了方便的数据持久化服务。通过使用Hibernate,我们可以将数据库操作转换为对Java对象的操作,从而简化了数据库...

    Hibernate入门教程.pdf

    ### Hibernate入门教程知识点详解 #### 一、Hibernate框架简介 **Hibernate** 是一款开放源代码的**对象关系映射(Object-Relational Mapping,简称ORM)**框架,它为Java应用提供了一种高效的机制,用于处理Java...

    Hibernate入门到精通.pdf

    《Hibernate入门到精通》这本书是针对Java开发人员深入学习Hibernate框架的一份宝贵资源。Hibernate是一个开源的对象关系映射(ORM)框架,它极大地简化了Java应用程序与数据库之间的交互。通过使用Hibernate,...

    hibernate入门

    **hibernate入门** Hibernate 是一个强大的Java持久化框架,它简化了数据库操作,使得开发者无需直接编写SQL语句即可实现对象与关系数据库之间的映射。这个文档将带你步入Hibernate的世界,了解其基本概念和核心...

    MyEclipse Hibernate 快速入门中文版

    《MyEclipse Hibernate 快速入门中文版》是专为初学者设计的指南,旨在帮助开发者迅速掌握在MyEclipse集成开发环境中使用Hibernate框架的基本操作和应用。此资源包括一个HTML文档(MyEclipse_Hibernate_Quickstart_...

    hibernate入门教程

    Hibernate的入门学习主要包括理解这些基本概念和操作,后续深入学习则会涉及到复杂映射、事务处理、性能优化和缓存管理等高级话题。随着不断实践和学习,开发者可以充分利用Hibernate框架提供的各种特性,编写更加...

    hibernate入门实例操作步骤

    **hibernate入门实例操作步骤** Hibernate是一款强大的Java对象关系映射(ORM)框架,它极大地简化了数据库操作,使得开发者可以使用Java对象的方式处理数据库事务。本篇将详细介绍Hibernate入门实例的操作步骤,...

    hibernate入门简单实例

    以下是关于Hibernate入门的一些关键知识点: 1. **对象关系映射(ORM)**:ORM是将数据库中的表映射为Java类的过程,通过这种方式,我们可以使用面向对象的编程方式来操作数据,而无需直接编写SQL语句。 2. **...

    hibernate入门源代码

    **Hibernate入门源代码详解** Hibernate 是一款开源的对象关系映射(ORM)框架,它极大地简化了Java应用程序对数据库的操作。这个资源包包含了“chapter07”目录下的源代码,是学习Hibernate基础知识的理想起点。让...

    hibernate入门数据简单插入

    标题"hibernate入门数据简单插入"指的是使用Hibernate框架进行数据库的基本操作,特别是数据的插入。Hibernate是一个开源的对象关系映射(ORM)框架,它允许Java开发者在应用程序中处理数据库对象,而无需直接编写...

    hibernate教程,hibernate入门

    **Hibernate 教程:带你入门持久化框架** Hibernate 是一个流行的开源对象关系映射(ORM)框架,它为 Java 应用程序提供了便捷的数据持久化服务。本教程将引导你逐步了解 Hibernate 的基本概念、安装配置以及核心...

    hibernate入门小程序

    **hibernate入门小程序** Hibernate 是一款开源的对象关系映射(ORM)框架,它为Java开发者提供了方便的数据持久化服务,使得开发人员可以使用面向对象的方式来操作数据库,而无需过多地关注SQL语句的编写。在...

    02_传智播客hibernate教程_hibernate入门案例的细节分析

    【标题】:“02_传智播客hibernate教程_hibernate入门案例的细节分析” 在本教程中,我们将深入探讨Hibernate,一个流行的Java对象关系映射(ORM)框架,它简化了数据库操作,使开发者可以更加专注于业务逻辑而不是...

Global site tag (gtag.js) - Google Analytics