书籍是全世界的营养品。生活里没有书籍,就好像没有阳光;智慧里没有书籍,就好像鸟儿没有翅膀。
目录 / 分类
数据库基础
数据库原理
SQL语言
网络原理
DB4O
Access
基础知识
驱动及连接
试题参考
技术手册
应用案例
常见问题
SQLServer
基础知识
驱动及连接
管理工具
技术手册
应用案例
常见问题
MySQL
基础知识
驱动连接
管理工具
技术手册
应用案例
常见问题
SQLite
基础知识
驱动及连接
管理工具
技术手册
应用案例
常见问题
Oracle
基础知识
驱动连接
管理工具
技术手册
应用案例
常见问题
PostgreSQL
基础知识
驱动及连接
管理工具
技术手册
应用案例
常见问题
移动应用
JavaME
Android
微信开发
经验分享
Java组件
Java开发
应用办公
常见问题解决
Delphi
硬件故障解决
WEB
HTML5
Javascript
速查表
文件同步
服务器配置
Apache
Tomcat
Resin
协议&概念
IIS&ASP
win&linux
Absolute Database
nginx
OpenFire
Redis
freeswitch
网文摘录
IT杂谈
网文转载
行业新闻
热点推荐
下载中心
软件下载
CUBRID数据库
介绍及使用
验证/二维/条形码
验证码原理及实现
二维码相关
条形码相关
在线二维码生成
在线条形码生成
当前位置:
首页
>
MySQL
>
技术手册
hibernate-事务管理
Hibernate 是JDBC 的轻量级封装,本身并不具备事务管理能力。在事务管理层,
Hibernate将其委托给底层的JDBC或者JTA,以实现事务管理和调度功能。
Hibernate的默认事务处理机制基于JDBC Transaction。我们也可以通过配置文
件设定采用JTA作为事务管理实现:
Java代码
<hibernate-configuration>
<session-factory>
……
<property name=
"hibernate.transaction.factory_class"
>
net.sf.hibernate.transaction.JTATransactionFactory
<!--net.sf.hibernate.transaction.JDBCTransactionFactory-->
</property>
……
</session-factory>
</hibernate-configuration>
基于JDBC的事务管理
将事务管理委托给JDBC 进行处理无疑是最简单的实现方式,Hibernate 对于JDBC事务的封装也极为简单。
我们来看下面这段代码:
Java代码
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
……
tx.commit();
从JDBC层面而言,上面的代码实际上对应着:
Java代码
Connection dbconn = getConnection();
dbconn.setAutoCommit(
false
);
……
dbconn.commit();
就是这么简单,Hibernate并没有做更多的事情(实际上也没法做更多的事情),只是将这样的JDBC代码进行了封装而已。
这里要注意的是,在sessionFactory.openSession()中,hibernate会初始化数据库连接,与此同时,将其AutoCommit 设为关闭状态(false)。而其后,在Session.beginTransaction 方法中,Hibernate 会再次确认Connection 的AutoCommit 属性被设为关闭状态( 为了防止用户代码对session 的Connection.AutoCommit属性进行修改)。
这也就是说,我们一开始从SessionFactory获得的session,其自动提交属性就已经被关闭(AutoCommit=false),下面的代码将不会对数据库产生任何效果:
Java代码
session = sessionFactory.openSession();
session.save(user);
session.close();
这实际上相当于 JDBC Connection的AutoCommit属性被设为false,执行了若干JDBC操作之后,没有调用commit操作即将Connection关闭。如果要使代码真正作用到数据库,我们必须显式的调用Transaction指令:
Java代码
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
基于JTA的事务管理
JTA 提供了跨Session 的事务管理能力。这一点是与JDBC Transaction 最大的差异。
JDBC事务由Connnection管理,也就是说,事务管理实际上是在JDBC Connection中实现。事务周期限于Connection的生命周期之类。同样,对于基于JDBC Transaction的Hibernate 事务管理机制而言,事务管理在Session 所依托的JDBC Connection中实现,事务周期限于Session的生命周期。
JTA 事务管理则由 JTA 容器实现,JTA 容器对当前加入事务的众多Connection 进
行调度,实现其事务性要求。JTA的事务周期可横跨多个JDBC Connection生命周期。
同样对于基于JTA事务的Hibernate而言,JTA事务横跨可横跨多个Session。
JTA 事务是由JTA Container 维护,而参与事务的Connection无需对事务管理进行干涉。这也就是说,如果采用JTA Transaction,我们不应该再调用HibernateTransaction功能。
上面基于JDBC Transaction的正确代码,这里就会产生问题:
Java代码
public
class
ClassA{
public
void
saveUser(User user){
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
}
}
public
class
ClassB{
public
void
saveOrder(Order order){
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(order);
tx.commit();
session.close();
}
}
public
class
ClassC{
public
void
save(){
……
UserTransaction tx =
new
InitialContext().lookup(“……”);
ClassA.save(user);
ClassB.save(order);
tx.commit();
……
}
}
这里有两个类ClassA和ClassB,分别提供了两个方法:saveUsersaveOrder,
用于保存用户信息和订单信息。在ClassC中,我们接连调用了ClassA.saveUser方法和ClassB.saveOrder 方法,同时引入了JTA 中的UserTransaction 以实现ClassC.save方法中的事务性。问题出现了,ClassA 和ClassB 中分别都调用了Hibernate 的Transaction 功能。在Hibernate 的JTA 封装中,Session.beginTransaction 同样也执行了InitialContext.lookup方法获取UserTransaction实例,Transaction.commit方法同样也调用了UserTransaction.commit方法。实际上,这就形成了两个嵌套式的JTA Transaction:ClassC 申明了一个事务,而在ClassC 事务周期内,ClassA 和ClassB也企图申明自己的事务,这将导致运行期错误。因此,如果决定采用JTA Transaction,应避免再重复调用Hibernate 的
Transaction功能,上面的代码修改如下:
Java代码
public
class
ClassA{
public
void
save(TUser user){
session = sessionFactory.openSession();
session.save(user);
session.close();
}
……
}
public
class
ClassB{
public
void
save (Order order){
session = sessionFactory.openSession();
session.save(order);
session.close();
}
……
}
public
class
ClassC{
public
void
save(){
……
UserTransaction tx =
new
InitialContext().lookup(“……”);
classA.save(user);
classB.save(order);
tx.commit();
……
}
}
上面代码中的ClassC.save方法,也可以改成这样:
Java代码
public
class
ClassC{
public
void
save(){
……
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
classA.save(user);
classB.save(order);
tx.commit();
……
}
}
实际上,这是利用Hibernate来完成启动和提交UserTransaction的功能,但这样的做法比原本直接通过InitialContext获取UserTransaction 的做法消耗了更多的资源,得不偿失。
在EJB 中使用JTA Transaction 无疑最为简便,我们只需要将save 方法配置为JTA事务支持即可,无需显式申明任何事务,下面是一个Session Bean的save方法,它的事务属性被申明为“Required”,EJB容器将自动维护此方法执行过程中的事务:
Java代码
/**
* @ejb.interface-method
* view-type="remote"
*
* @ejb.transaction type = "Required"
**/
public
void
save(){
//EJB环境中,通过部署配置即可实现事务申明,而无需显式调用事务
classA.save(user);
classB.save(log);
}
//方法结束时,如果没有异常发生,则事务由EJB容器自动提交。
上一篇:通过mysqlshowprocesslist命令检查mysql锁的方法
下一篇:mysql-bin.000001文件的来源及处理方法
本站文章内容,部分来自于互联网,若侵犯了您的权益,请致邮件chuanghui423#sohu.com(请将#换为@)联系,我们会尽快核实后删除。
Copyright © 2006-2023 DBMNG.COM All Rights Reserved. Powered by
DEVSOARTECH
豫ICP备11002312号-2
豫公网安备 41010502002439号