Hibernate JDBC traction

本文深入探讨了Hibernate如何封装JDBC事务处理,详细解释了Hibernate与JDBC事务的区别及配置方式,提供了实例代码说明,并揭示了不当使用事务可能引发的数据库死锁问题及正确处理方法。
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.youkuaiyun.com/he_hchx/article/details/1586409
### 如何在 SAP 中使用 TCode TRANSACTION 在 SAP 系统中,事务代码(Transaction Code, TC)用于启动特定的应用程序或功能模块。要执行名为 `TRANSACTION` 的事务代码,可以按照以下方法操作: #### 方法一:通过命令栏输入 1. 登录到 SAP GUI 客户端。 2. 在命令栏(Command Field),即窗口顶部的输入框内键入 `TRANSACTION`[^1]。 3. 按下回车键。 这将触发与该事务代码关联的功能或交易处理流程。 #### 方法二:创建快捷方式 为了更便捷地访问常用的事务代码,可以在桌面或其他位置创建指向此事务代码的快捷方式: - 右击桌面空白处选择新建 -> Internet Explorer 快捷方式; - 输入完整的 URL 地址,通常格式为 http://<your_sap_server>:<port>/sap/bc/gui/sap/its/webgui?~transaction=TRANSACTION 并替换 `<your_sap_server>` 和 `<port>` 为你实际使用的服务器地址和端口号; 需要注意的是,在某些情况下可能需要管理员权限才能成功创建这样的外部链接。 ```python # Python 示例代码展示如何模拟发送事务代码给 SAP 系统 import pyodbc def execute_transaction_code(transaction_code): conn_str = ( r'DRIVER={SAP};' r'SERVER=<server>;' r'DATABASE=<database>;' r'UID=<username>;' r'PWD=<password>' ) with pyodbc.connect(conn_str) as connection: cursor = connection.cursor() sql_command = f"CALL TRANSACTION '{transaction_code}'" cursor.execute(sql_command) execute_transaction_code('TRANSACTION') ``` 上述Python脚本仅作为概念验证用途,并不适用于生产环境中的真实部署。真实的集成场景应当遵循企业内部的安全策略和技术框架指南。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值