??xml version="1.0" encoding="utf-8" standalone="yes"?>
Hibernate可以配置为JDBCTransaction或者是JTATransactionQ这取决于你在hibernate.properties中的配置:
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory
如果你什么都不配|,默认情况下用JDBCTransactionQ如果你配置为:
hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
用JTATransaction
不管你准备让Hibernate使用JDBCTransactionQ还是JTATransactionQ我的忠告就是什么都不配Q将让它保持默认状态,如下Q?
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory
在下面的分析中我会给出原因?
一、JDBC Transaction
看看使用JDBC Transaction的时候我们的代码例子Q?
Session session = sf.openSession();
Transaction tx = session.beginTransactioin();
...
session.flush();
tx.commit();
session.close();
q是默认的情况,当你在代码中使用Hibernate的Transaction的时候实际上是JDBCTransaction。那么JDBCTransactionI竟是什么东西呢Q来看看源代码就清楚了:
Hibernate2.0.3源代码中的类
net.sf.hibernate.transaction.JDBCTransaction:
public void begin() throws HibernateException {
...
if (toggleAutoCommit) session.connection().setAutoCommit(false);
...
}
q是启动Transaction的方法,看到 connection().setAutoCommit(false) 了吗Q是不是很熟悉?
再来?
public void commit() throws HibernateException {
...
try {
if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush();
try {
session.connection().commit();
committed = true;
}
...
toggleAutoCommit();
}
q是提交ҎQ看到connection().commit() 了吗Q下面就不用我多说了Q这个类代码非常单易懂,通过阅读使我们明白Hibernate的Transaction都在q了些什么?我现在把?Hibernate写的例子译成JDBCQ大家就一目了然了Q?
Connection conn = ...; <--- session = sf.openSession();
conn.setAutoCommit(false); <--- tx = session.beginTransactioin();
... <--- ...
conn.commit(); <--- tx.commit(); (对应左边的两?
conn.setAutoCommit(true);
conn.close(); <--- session.close();
看明白了吧,Hibernate的JDBCTransactionҎ是conn.commit而已Q根本毫无神U可aQ只不过在Hibernate 中,Session打开的时候,׃自动conn.setAutoCommit(false)Q不像一般的JDBCQ默认都是trueQ所以你最后不?commit也没有关p,׃Hibernate已经把AutoCommitl关掉了Q所以用Hibernate的时候,你在E序中不?Transaction的话Q数据库Ҏ没有反应?br />
如果你在EJB中用HibernateQ或者准备用JTA来管理跨Session的长事务Q那么就需要用JTATransactionQ先看一个例子:
javax.transaction.UserTransaction tx = new InitialContext().lookup("javax.transaction.UserTransaction");
Session s1 = sf.openSession();
...
s1.flush();
s1.close();
...
Session s2 = sf.openSession();
...
s2.flush();
s2.close();
tx.commit();
q是标准的用JTA的代码片断,Transaction是跨Session的,它的生命周期比Session要长。如果你在EJB中?HibernateQ那么是最单不q的了,你什么Transaction代码l统都不要写了,直接在EJB的部|描q符上配|某某方法是否用事务就可以了?
现在我们来分析一下JTATransaction的源代码Q?net.sf.hibernate.transaction.JTATransaction:
public void begin(InitialContext context, ...
...
ut = (UserTransaction) context.lookup(utName);
...
看清楚了吗? 和我上面写的代码 tx = new Initial Context?().lookup("javax.transaction.UserTransaction"); 是不是完全一P
public void commit() ...
...
if (newTransaction) ut.commit();
...
JTATransaction的控制稍微复杂,不过仍然可以很清楚的看出来Hibernate是如何封装JTA的Transaction代码的?
但是你现在是否看C什么问题? 仔细想一下,Hibernate Transaction是从Session中获得的Qtx = session.beginTransaction()Q最后要先提交txQ然后再session.closeQ这完全W合JDBC?Transaction的操作顺序,但是q个序是和JTA的Transactioin操作序d矛盾的!Q! JTA是先启动TransactionQ然后启动SessionQ关闭SessionQ最后提交TransactionQ因此当你用JTA?Transaction的时候,那么千万不要用Hibernate的TransactionQ而是应该像我上面的JTA的代码片断那样用才行?
ȝQ?
1、在JDBC上用Hibernate
必须写上Hibernate Transaction代码Q否则数据库没有反应。此时Hibernate的Transaction是Connection.commit而已
2、在JTA上用Hibernate
写JTA的Transaction代码Q不要写Hibernate的Transaction代码Q否则程序会报错
3、在EJB上用Hibernate
什么Transactioin代码都不要写Q在EJB的部|描q符里面配置
|---CMT(Container Managed Transaction)
|
|---BMT(Bean Managed Transaction)
|
|----JDBC Transaction
|
|----JTA Transaction
--------------------------------------------------------------------------------
提问Q?
javax.transaction.UserTransaction tx = new InitialContext().lookup("javax.transaction.UserTransaction");
Session s1 = sf.openSession();
...
s1.flush();
s1.close();
...
Session s2 = sf.openSession();
...
s2.flush();
s2.close();
tx.commit();
s1不关闭,使用s2q行操作的代码中使用s1可不可以Q我觉得q样更加节约资源Q不需要反复的q接、关闭)
但sf.opengSession()Ӟq没有setAutoCommit(false)Q我想问的是Q如果不~写M事务代码Q如Q?
Session s = sf.openSession();
......
s.close();
数据库会不会有反应(此时应该是默认AutoCommit为trueQ?
不会有反应。在sf.openSession() 创徏Session实例的时候,已l调用了conn.setAutoCommit(false)了?
另外Q我想问一下:
1. s.flush()是不是必ȝ
2. s.close()是不是一定要关闭
--------------------------------------------------------------------------------
回答Q?
s.flush不是必须的,s.close()会调用一ơs.flush()
s.close()正常情况下应该关闭,除非你是用ThreadLocal理Session?
s1不关闭,使用s2q行操作的代码中使用s1可不可以Q我觉得q样更加节约资源Q不需要反复的q接、关闭)
在这个例子中看不出来JTA的作用?
假设
Class A {
find() {
Session s1 = sf.openSession();
...
s1.flush();
s1.close();
}
}
Class B {
find() {
Session s2 = sf.openSession();
...
s2.flush();
s2.close();
}
}
Main {
tx = ...;
A.find();
B.find();
tx.commit();
} Q全文完Q?
Atomic(原子?:指整个数据库事务是不可分割的工作单元,只有事务中所有的操作执行成功,才算整个事务成功.
Consistency(一致?:指数据库事务不能破换关系数据的完整性以及业务逻辑上的一致?比如说银行{帐事?不管事务成功q是
p|,应该保证事务l束后的存款总额为原来的.)
Isolation(隔离?:指在q发环境?当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空?
Durability(持久?:指的是只要事务成功工l束,它对数据库所做的更新必L久保存下?即发生pȝ崩溃,从新启动数据库系l后,数据库还能恢复到事务成功l束时候的状?
数据库管理系l采用日志来保证事务的原子?一致性和持久?日志记录了事务对数据库所做的更新,如果某个事务在执行过E中发生错误,可以根据日?撤消事务Ҏ据库已做的更?使数据库退回到执行事务前的初始状?
数据库管理系l采用锁机制来实C务的隔离?当多个事务同时更新数据库中的相同的数据时,只允许只有锁的事务能更新该数?其他事务必须{待,直到前一个事务释放了?其他事务才有Z更新该数据?/p>
(POJOs IN ACTION中文?
隔离的(isolatedQ数据库事务
有时Q你可以直接依赖数据库本w处理共享数据的q发讉K。可以将数据库配|成执行怺隔离QisolatedQ用数据库的行话来讲Q的数据库事务。如果你q不熟悉q一概念Q请别担心,W?2章里会进行详l说明。眼下最关键的是要记住,如果应用E序使用完全隔离的事务,那么同时执行两个事务的效果将与一个接一个执行这两个事务完全{效?br />
从表面上看,q种Ҏ看似非常单,但这cM务也存在问题Q由于隔M务如何实现完全由数据库决定,因此有时它们会导致性能降低Qo人无法接受。鉴于此Q许多应用程序都避免使用q类事务Q{而采用所谓的乐观QoptimisticQ或者悲观(pessimisticQ锁Q稍后将作描q?/p>
乐观?br />
处理q发更新的一U方式是使用乐观锁(optimistic lockingQ。乐观锁的工作原理是让应用程序检查它卛_更新的数据是否已被另一个事务修改(自该数据上次d以来Q。实C观锁的一U常见做法是在每个表里添加一个版本字D,每次应用E序更新数据表记录时增加这个版本字Dc每个UPDATE语句中的WHERE子句会根据上ơ读取的值来判断q个版本h否改变。通过查看PreparedStatement.executeUpdate()q回的记录数Q应用程序可以判断UPDATE语句是否成功。如果这条记录已被另一个事务更新或删除Q应用程序可以回滚这个事务,q新开始?br />
在直接执行SQL语句的应用程序中Q乐观锁机制的实现非常容易。不q,使用诸如JDO和Hibernate的持久层构架Ӟ实现更ؓҎQ因为它们已乐观锁作ؓ配置选项提供。一旦启用该配置选项Q持久层框架会自动生成SQL UPDATE语句Q执行版本检查。第12章将分析乐观锁的使用时机及其~点Qƈ向你展示怎样在iBATIS、JDO和Hibernate中用乐观锁?br />
乐观锁的名称源自如下假定情况Q即q发更新的几率极,此外应用E序q不Lq发更新Q而是ƈ发更斎ͼq从q发更新中恢复过来。另一U方式是使用悲观锁(pessimistic lockingQ,它假定ƈ发更新将会发生,因此必须预先L?/p>
悲观?/p>
不同于乐观锁的另一U方式是使用悲观锁。当d某些记录Ӟ事务先锁住这些记录,q样可以防止其他事务讉Kq些数据记录。具体细节要视数据库而定Q不q糟p的是,q所有数据库都支持悲观锁。如果数据库支持悲观锁,在直接执行SQL语句的应用程序中Q实现悲观锁非常Ҏ。然而,正如你所预料的,在JDO或Hibernate应用E序中用悲观锁更ؓҎ。JDO以配|选项的方式提供悲观锁Q而Hibernate则提供一个简单实用的APIQ来锁定对象。同P在第12章,你将学习何时使用悲观锁,分析其缺点,q看看怎样在iBATIS、JDO和Hibernate中用悲观锁?/p>
除了处理单个数据库事务里的ƈ发,通常你还必须处理跨一pd数据库事务的q发