`
啸笑天
  • 浏览: 3461066 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

Hibernate事务

阅读更多

JDBCTransaction 

单个数据库(一个SesisonFactory对应一个数据库),由JDBC实现。

Session session = null;
Transaction tx =null;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();//相当于JDBC的connection.setAutoCommit(false);
//process
tx.commit();//相当于JDBC的connection.commit();
} catch(HibernateException e){
if(tx != null)tx.rollback();//相当于JDBC的connection.rollback();
                 throw e;
}finally {
if (session != null)session.close();
}
  

JTATransaction(分布式事务,垮数据库,比如说银行转账,就需要这种跨数据库的事务来操作)

可以简单的理解成跨数据库的事物,由应用JTA 容器实现;使用JTATransaction需要配置hibernate.transaction.factory_class参数,该参数缺省值 是org.hibernate.transaction. JDBCTransactionFactory,当使用JTATransaction时需要将该参数改成org.hibernate.transaction.JTATransactionFactory,并配置jta.UserTransaction参数JNDI(Hibernate在启动JTATransaction时要用该值到JNDI的上下文Context中去找javax.transaction.UserTransaction)

javax.transaction.UserTransactin tx = context.lookup(“jndiName”);
try{
tx.begin();
//多个数据库的session操作;
//session1….
//session2….
tx.commit();
}catch(Exception e){
tx.rollback();
        throw e;
}
 
session context和事务边界

事务边界:即事务开启,提交,关闭这些代码的位置。

mvc三层架构的思想上,事务边界的处理应该放在业务逻辑层中,但是Transaction对象是dao层的,所以要采用spring这种框架来实现明确的mvc分层。

Open session in view解决事务边界问题和数据懒加载问题。

Open session in view带来的问题:

sessiontransaction的时间延长。如果对数据加锁那就更长时间占用对象,session延长对内存的占用时间更长,对内存大小要求更大,且和数据库长时间交互,数据库的并发能力降低

 

 

current_session_context_class属性来定义context(用sessionFactory.getCurrentSession()来获得session),其值为:

1.threadThreadLocal来管理Session实现多个操作共享一个Session,避免反复获取Session,并控制事务边界,此时session不能调用closecommitrollback的时候session会自动关闭(connection.release_mode:after_transaction)Open session in view:在生成(渲染)页面时保持 session打开。

2.jta:由JTA事务管理器来管理事务(connection.release_mode:after_statement)

用图理解:

从图中可以显示:客户端看到viewHTML时session还没有关闭,session要消息4后Filter中关闭。

session的范围扩大到整个请求的范围内,这样在一方面很好的解决了懒加载session关闭的问题,另一方面一次请求变成了一个事务,那么用户做的更新操作对数据库来说都是一条sql语句了。

但是放大了session范围,如果网速比较慢,那么session就会一直打开,一级缓存的数据得不到释放,还有事务本应当在业务逻辑层开启关闭的,也放大到了整个请求。

code:

HibernateUtil.java

 

package cn.itcast.hibernate;
import java.io.Serializable;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
//工具类一般不需要更改,所以final
public final class HibernateUtil {
	private static SessionFactory sessionFactory;
	private static ThreadLocal session = new ThreadLocal();//把ThreadLocal当成一个Map容器
    //禁止别的类new
	private HibernateUtil() {
	}

	static {
		Configuration cfg = new Configuration();
		cfg.configure();
		sessionFactory = cfg.buildSessionFactory();
	}

	public static Session getThreadLocalSession() {
		Session s = (Session) session.get();//ThreadLocal的key是默认的,可以把key理解为当前线程
		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);
		}
	}

	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}
}

 OpenSessionInView.java过滤器。负责从ThreadLocal中获得session和关闭session

 

package com.taobao.hibernate;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class OpenSessionInView implements Filter {

	public void destroy() {
	}

	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain arg2) throws IOException, ServletException {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtil.getThreadLocalSession();
			tx = session.beginTransaction();
			arg2.doFilter(arg0, arg1);
			tx.commit();
		} catch (Exception e) {
			if (tx != null)
				tx.rollback();
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			HibernateUtil.closeSession();
		}

	}

	public void init(FilterConfig arg0) throws ServletException {
	}

}
 然后在业务层可以处理多个业务数据,在dao层获得过滤器打开的session处理数据和数据库的交互。

悲观锁和乐观锁

悲观锁由数据库来实现,从读取的时候开始加锁,直到修改完成。

缺点:读取完以后,用户修改过程缓慢,造成同步性降低。

乐观锁hibernateversiontimestamp来实现。两人同时编辑时候,假设获取的版本号都为1,编辑完提交的时候,版本号为2,第一个提交完以后,数据库版本号为2,第二个提交的时候对比版本号就会报错。 

code:

给Users加上版本号

Users.java

 

import java.util.Date;  
  
public class Users {  
    private int id;  
    private String name;  
    private Date birthday;  
    private int ver;  
      
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public Date getBirthday() {  
        return birthday;  
    }  
    public void setBirthday(Date birthday) {  
        this.birthday = birthday;  
    }  
    public void setVer(int ver) {  
        this.ver = ver;  
    }  
    public int getVer() {  
        return ver;  
    }  
}  

 Users.hbm.xml

 

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.taobao.hibernate.domain">
	<class name="User">
		<id name="id">
			<generator class="native" />
		</id>
		<version name="ver"/><!--版本号,时间戳必须写在id后面--><!--也可以使用<timestamp name=""/>,但version标签可以铜鼓type指定不同类型-->
		<!-- <property name="name" /> -->
		<component name="name">
			<property name="firstName" column="first_name"/>
			<property name="lastName" column="last_name" />
		</component>
		<property name="birthday" />
	</class>
</hibernate-mapping>

 VersionTest.java

 

package com.taobao.hibernate;

import java.util.Date;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.taobao.hibernate.domain.Name;
import com.taobao.hibernate.domain.User;

public class VersionTest {

	public static void main(String[] args) {
		User user = new User();
		user.setBirthday(new Date());
		Name n = new Name();
		n.setFirstName("firstName");
		n.setLastName("lastName");
		user.setName(n);
		// 111
		addUser(user);
		// System.out.println("id: " + user.getId());
		// 222
		System.out.println("1111111");
		update(user.getId());
	}

	static void update(int id) {
		Session s1 = null;
		s1 = HibernateUtil.getSession();
		Transaction tx1 = s1.beginTransaction();
		User user1 = (User) s1.get(User.class, id);

		Session s2 = HibernateUtil.getSession();
		Transaction tx2 = s2.beginTransaction();
		User user2 = (User) s2.get(User.class, id);

		user1.getName().setFirstName("new1 firstName");

		user2.getName().setFirstName("new2 firstName");

		tx1.commit();
		tx2.commit();

		

		s1.close();
		s2.close();
	}

	static void addUser(User user) {
		Session s = null;
		Transaction tx = null;
		try {
			s = HibernateUtil.getSession();
			tx = s.beginTransaction();
			s.save(user);
			// 333
			// s.persist(user);
			Name n = new Name();
			n.setFirstName("firstName");
			n.setLastName("lastName");
			user.setName(n);
			user.setBirthday(new Date());
			tx.commit();
			user.setBirthday(new Date());
			tx = s.beginTransaction();
			tx.commit();
			// 444
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			throw e;
		} finally {
			if (s != null)
				s.close();
		}
	}

	static void addUser1(User user) {
		Session s = null;
		Transaction tx = null;
		try {
			s = HibernateUtil.getSession();
			tx = s.beginTransaction();
			s.save(user);
			tx.commit();
		} finally {
			if (s != null)
				s.close();
		}
	}
}
 拟两个线程同步操作,更新user

运行结果如下

Hibernate: insert into Users (ver, name, birthday) values (?, ?, ?)

Hibernate: select users0_.id as id0_0_, users0_.ver as ver0_0_, users0_.name as name0_0_, users0_.birthday as birthday0_0_ from Users users0_ where users0_.id=?

Hibernate: update Users set ver=?, name=?, birthday=? where id=? and ver=?

Hibernate: update Users set ver=?, name=?, birthday=? where id=? and ver=?

Exception in thread "main" org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [domain.Users#1]

第二个提交的事务内报错,数据库内字段修改为new2。

 

 

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

相关推荐

    Spring Hibernate 事务处理 详细说明

    3. **Hibernate事务配置:**在Spring中,需要配置Hibernate SessionFactory,并将其注入到需要进行数据库操作的服务中。同时,通过`PlatformTransactionManager`接口(如HibernateTransactionManager)配置事务管理...

    Spring Hibernate事务实例

    2. Hibernate事务管理:使用`HibernateTransactionManager`结合SessionFactory进行事务控制。 3. AOP(面向切面编程)在事务管理中的应用:`TransactionInterceptor`基于AOP拦截方法调用,处理事务。 4. 配置事务...

    hibernate事务管理机制.doc

    【hibernate事务管理机制】是指在使用Hibernate框架进行数据库操作时,如何管理和协调事务的一系列规则和策略。事务管理是确保数据一致性、完整性和并发控制的重要机制。 **悲观锁**是预防性的锁定策略,它假设并发...

    Hibernate事务(源码)

    **Hibernate事务管理详解** 在Java开发中,尤其是在企业级应用中,事务管理是不可或缺的一部分。Hibernate作为一款流行的ORM(对象关系映射)框架,提供了强大的事务处理能力。本篇文章将深入探讨Hibernate中的事务...

    详解Hibernate事务处理机制

    ### 详解Hibernate事务处理机制 #### 一、引言 Hibernate作为一款优秀的对象关系映射(ORM)框架,在Java开发领域扮演着极其重要的角色。它不仅简化了数据持久化的复杂性,还提供了一系列强大的功能来支持高效的...

    spring hibernate 事务管理学习笔记(一)

    本文将深入探讨Spring与Hibernate整合时的事务管理,帮助你更好地理解和运用这些技术。 首先,Spring框架是Java企业级应用的基石,它提供了一种依赖注入(Dependency Injection,DI)的方式,使得组件之间的耦合度...

    hibernate事务,并发及缓存管理实例

    一、Hibernate事务管理 在数据库操作中,事务确保了数据的一致性和完整性。Hibernate提供了四种事务隔离级别:读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)和串行化...

    在Spring中配置Hibernate事务

    在Spring框架中集成和配置Hibernate事务管理是企业级Java应用中的常见实践,它能提供高效且灵活的事务处理策略。Spring作为一款强大的依赖注入(DI)和面向切面编程(AOP)容器,能够轻松地管理和协调不同数据访问...

    Hibernate 事务和并发控制

    本文将深入探讨Hibernate中的事务和并发控制,这对于开发高效、稳定的数据库应用至关重要。 首先,我们来理解Hibernate中的事务管理。在数据库操作中,事务是保证数据一致性的重要手段。一个事务包含了一组数据库...

    spring hibernate 事务管理学习笔记(二)

    在本篇“Spring Hibernate 事务管理学习笔记(二)”中,我们将深入探讨Spring框架与Hibernate集成时如何实现高效、安全的事务管理。这是一篇关于源码分析和技术工具使用的文章,适合对Java开发和数据库操作有基础...

    hibernate事务

    Hibernate事务管理是Java开发中非常重要的一个环节,尤其是在企业级应用开发中,它与数据库的交互密切相关,确保数据的一致性和完整性。Hibernate作为一款流行的ORM(对象关系映射)框架,提供了一种方便的方式来...

    JDBC和hibernate事务的详解

    **JDBC与Hibernate事务详解** 在Java开发中,数据库事务管理是确保数据一致性、完整性和原子性的重要机制。本讲解将深入探讨JDBC(Java Database Connectivity)和Hibernate两种不同的技术在处理事务时的方法和特点...

    hibernate 事务管理注意事项

    ### hibernate 事务管理注意...综上所述,Hibernate事务管理的合理配置对于保证系统的稳定性和数据一致性至关重要。开发者应该充分了解Hibernate的缓存机制及其对事务管理的影响,并根据实际情况灵活调整事务管理策略。

    spring mvc+hibernate 实现事务管理(全注解版)

    2. **Hibernate事务**: Hibernate本身也提供了一种事务管理机制,但在Spring环境中,我们通常使用Spring的事务管理器来协调。当@Transactional注解应用于方法上,Spring会在该方法执行前后自动管理事务的开始和结束...

    spring配置hibernate事务

    在Spring框架中配置Hibernate事务管理是一项关键任务,它允许开发者以声明式的方式处理数据库操作的事务性,确保数据的一致性和完整性。以下是如何在Spring中配置Hibernate事务的详细步骤和概念解释。 首先,理解...

    Hibernate事务控制[定义].pdf

    "Hibernate事务控制"主要关注在Hibernate中如何管理和协调事务,以满足ACID原则,即原子性、一致性、隔离性和持续性。 首先,事务是数据库操作的基本单元,它确保一系列数据库操作要么全部成功,要么全部回滚。原子...

    Spring AOP管理Hibernate事务(TransactionInSpringAOP)

    本篇文章将深入探讨如何在Spring AOP中实现Hibernate事务管理,以及这一过程中的关键概念和技术细节。 首先,让我们了解什么是Spring AOP。AOP是一种编程范式,它允许程序员定义“切面”,这些切面是跨越多个对象的...

    spring整合hibernate实现事务处理

    在`Spring_1800_Spring_Hibernate_Transaction_Annotation`这个压缩包文件中,很可能包含了使用注解方式实现Spring整合Hibernate事务处理的相关示例代码和配置文件。通过阅读和理解这些代码,你可以更好地掌握这一...

Global site tag (gtag.js) - Google Analytics