Hibernate是对JDBC的轻量级对象封装,Hibernate本身是不具备Transaction处理功能的,
Hibernate的Transaction实际上是底层的JDBC Transaction的封装,或者是JTA Transaction的封装。
Hibernate可以配置为JDBCTransaction或者是JTATransaction,这取决于你在hibernate.properties中的配置:
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory
如果你什么都不配置,默认情况下使用JDBCTransaction。建议是什么都不配,将让它保持默认状态。
一、Transaction
HIbernate对于JDBC事物的封装是极为简单的,看看使用JDBC Transaction的时候我们的代码例子:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransactioin();
...
session.flush();
tx.commit();
session.close();
详细的信息我们查看一下Hibernate2.0.3源代码中的类
net.sf.hibernate.transaction.JDBCTransaction:
public void begin() throws HibernateException {
...
if (toggleAutoCommit) session.connection().setAutoCommit(false);
...
}
这是启动Transaction的方法,看到 connection().setAutoCommit(false) 了吗?是不是很熟悉?
再来看
public void commit() throws HibernateException {
...
try {
if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush();
try {
session.connection().commit();
committed = true;
}
...
toggleAutoCommit();
}
这是提交方法,看到connection().commit() 了吗?下面就不用我多说了,这个类代码非常简单易懂,通过阅读使我们明白Hibernate的Transaction都在干了些什么?我现在把用Hibernate写的例子翻译成JDBC,大家就一目了然了:
Connection conn = ...; <--- session = sf.openSession();
conn.setAutoCommit(false); <--- tx = session.beginTransactioin();
... <--- ...
conn.commit(); <--- tx.commit(); (对应左边的两句)
conn.setAutoCommit(true);
conn.close(); <--- session.close();
就是这么简单,Hibernate只是将这样的JDBC代码进行了封装而已。
这里要注意的是,在Hibernate中,Session打开的时候,即sessionFactory.openSession()中,hibernate会初始化数据库连接,于此同时设置conn.setAutoCommit(false)。而后,在session.beginTracsaction方法中,Hibernate会再次确认Connection的AutoCommit属性被设置为关闭状态(false),防止用户代码对session的Connection.AutoCommit()属性进行修改。不像一般的JDBC,默认都是true,所以用Hibernate的时候,你在程序中不写Transaction的话,数据库根本就没有反应。
二、setAutoCommit
void setAutoCommit(boolean autoCommit)throws SQLException
参数: autoCommit - 为 true 表示启用自动提交模式;为 false 表示关闭提交模式。如果connection.setAutoCommit(false);的话,则在语句正常执行完毕后需要用connection.commit()手动提交,如果在执行语句时出错的可以调用connection.rollback()来回滚!
将此连接的自动提交模式设置为给定状态。如果连接处于自动提交模式下,则将执行其所有 SQL 语句,并将这些语句作为单独的事务提交。否则,其 SQL 语句将成组地进入通过调用 commit 方法或 rollback 方法终止的事务中。默认情况下,新的连接处于自动提交模式下。
注:误用Connection.setAutoCommit导致的数据库死锁问题。
Connection con = null;
try{
con = getConnection();
con.setAutoCommit(false);
/*
* update USER set name=’winson’ where id=’000001’;
*/
con.commit();
}finally{
if(con!=null){
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
分析:问题就出现在第4行,写代码的人把数据库连接con 设置成非自动提交,但没有在执行出现异常的时候进行回滚。如果在执行第5行的时候出现异常,con既没有提交也没有回滚,表USER就会被锁住(如果oracle数据库就是行锁),而这个锁却没有机会释放。有人会质疑,在执行con.close()的时候不会释放锁吗?因为如果应用服务器使用了数据库连接池,连接不会被断开。
参考正确的写法应该是:
Connection con = null;
try{
con = getConnection();
con.setAutoCommit(false);
/*
* do what you want here.
*/
con.commit();
}catch(Throwable e){
if(con!=null){
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
throw new RuntimeException(e);
}finally{
if(con!=null){
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
参考:
http://www.360doc.com/content/10/0226/11/888785_16865620.shtml
http://jianrc.iteye.com/blog/52044
http://blog.csdn.net/he_hchx/article/details/1586409
Hibernate可以配置为JDBCTransaction或者是JTATransaction,这取决于你在hibernate.properties中的配置:
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory
如果你什么都不配置,默认情况下使用JDBCTransaction。建议是什么都不配,将让它保持默认状态。
一、Transaction
HIbernate对于JDBC事物的封装是极为简单的,看看使用JDBC Transaction的时候我们的代码例子:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransactioin();
...
session.flush();
tx.commit();
session.close();
详细的信息我们查看一下Hibernate2.0.3源代码中的类
net.sf.hibernate.transaction.JDBCTransaction:
public void begin() throws HibernateException {
...
if (toggleAutoCommit) session.connection().setAutoCommit(false);
...
}
这是启动Transaction的方法,看到 connection().setAutoCommit(false) 了吗?是不是很熟悉?
再来看
public void commit() throws HibernateException {
...
try {
if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush();
try {
session.connection().commit();
committed = true;
}
...
toggleAutoCommit();
}
这是提交方法,看到connection().commit() 了吗?下面就不用我多说了,这个类代码非常简单易懂,通过阅读使我们明白Hibernate的Transaction都在干了些什么?我现在把用Hibernate写的例子翻译成JDBC,大家就一目了然了:
Connection conn = ...; <--- session = sf.openSession();
conn.setAutoCommit(false); <--- tx = session.beginTransactioin();
... <--- ...
conn.commit(); <--- tx.commit(); (对应左边的两句)
conn.setAutoCommit(true);
conn.close(); <--- session.close();
就是这么简单,Hibernate只是将这样的JDBC代码进行了封装而已。
这里要注意的是,在Hibernate中,Session打开的时候,即sessionFactory.openSession()中,hibernate会初始化数据库连接,于此同时设置conn.setAutoCommit(false)。而后,在session.beginTracsaction方法中,Hibernate会再次确认Connection的AutoCommit属性被设置为关闭状态(false),防止用户代码对session的Connection.AutoCommit()属性进行修改。不像一般的JDBC,默认都是true,所以用Hibernate的时候,你在程序中不写Transaction的话,数据库根本就没有反应。
二、setAutoCommit
void setAutoCommit(boolean autoCommit)throws SQLException
参数: autoCommit - 为 true 表示启用自动提交模式;为 false 表示关闭提交模式。如果connection.setAutoCommit(false);的话,则在语句正常执行完毕后需要用connection.commit()手动提交,如果在执行语句时出错的可以调用connection.rollback()来回滚!
将此连接的自动提交模式设置为给定状态。如果连接处于自动提交模式下,则将执行其所有 SQL 语句,并将这些语句作为单独的事务提交。否则,其 SQL 语句将成组地进入通过调用 commit 方法或 rollback 方法终止的事务中。默认情况下,新的连接处于自动提交模式下。
注:误用Connection.setAutoCommit导致的数据库死锁问题。
Connection con = null;
try{
con = getConnection();
con.setAutoCommit(false);
/*
* update USER set name=’winson’ where id=’000001’;
*/
con.commit();
}finally{
if(con!=null){
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
分析:问题就出现在第4行,写代码的人把数据库连接con 设置成非自动提交,但没有在执行出现异常的时候进行回滚。如果在执行第5行的时候出现异常,con既没有提交也没有回滚,表USER就会被锁住(如果oracle数据库就是行锁),而这个锁却没有机会释放。有人会质疑,在执行con.close()的时候不会释放锁吗?因为如果应用服务器使用了数据库连接池,连接不会被断开。
参考正确的写法应该是:
Connection con = null;
try{
con = getConnection();
con.setAutoCommit(false);
/*
* do what you want here.
*/
con.commit();
}catch(Throwable e){
if(con!=null){
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
throw new RuntimeException(e);
}finally{
if(con!=null){
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
参考:
http://www.360doc.com/content/10/0226/11/888785_16865620.shtml
http://jianrc.iteye.com/blog/52044
http://blog.csdn.net/he_hchx/article/details/1586409