hibernatejdbc:浅谈如何结合JDBC事务和Spring+Hibernate



  问题:客户在其数据库操作过程中需要我们工作流接口这样就需要将我们工作流操作和他们业  务操作置于同个事务中我们服务采用都是spring声明式事务而客户采用是对connection进行事务处理

  如何保证JDBC事务致性?

  想到解决方案:使用jta事务用tomcat+jotm提供事务管理器为什么开始就想到要使用jta事务??实际上我们和客户都是使用个数据库为了方便各自使用了区别数据库连接方式使用jta话确实有bt意思在里面但是事实上是我们反应都是jta最后没有采用该思路方法原因也很简单:我没有将jotm配置成功!汗

  想到解决方案 2:将客户这些特定代码用spring管理起来要修改客户部分代码这个方案遭到了客户强烈反对于是放弃

  想到解决方案 3:客户数据库操作和我们服务使用同个数据库连接然后编程处理事务存在两种方式:种是把客户连接传给我们种则是把我们连接传给客户种方式对我们影响太大所以最后决定采用后种方式:从hibernate session中获取connection然后传递给客户接下来查看下HibernateTemplateexecute思路方法思路就很简单了:获取定义sessionFactory-->创建个新session并打开-->将session和当前线程绑定-->给客户代码返回connection-->打开事务-->客户使用我们传递connection进行数据库操作-->我们不带声明事务服务操作-->提交事务-->解除绑定

  JDBC事务实际要注意地方是:

  1、将session和当前线程绑定使用TransactionSynchronizationManager.bindResource思路方法这样在HibernateTemplate里才能找到session;

  2、我们服务定要把声明式事务彻底干掉否则会有commit;

  3、我们服务完毕后定要flush session否则客户代码不会感知数据库里数据变化

  最终解决:使用了spring里常用模板和回调JDBC事务代码如下:

public  TransactionTemplate {  
    protected final Log logger = LogFactory.getLog(TransactionTemplate.);  
    private FlushMode flushMode = FlushMode.ALWAYS;  
    public Object execute(TransactionCallback callback) {  
        //首先获取sessionFactory  
        SessionFactory sessionFactory = (SessionFactory) Framework.getEngine  
                .getContainer.getComponent("sessionFactory");  
        //创建个新session并打开  
        logger.debug("Opening single Hibernate Session in TransactionTemplate");  
        Session session = getSession(sessionFactory);  
        //将session和当前线程绑定  
        TransactionSynchronizationManager.bindResource(sessionFactory,  SessionHolder(session));  
        //获取数据库连接  
        Connection conn = session.connection;  
        Object result = null;  
        Transaction transaction = null;  
        try {  
            //开始处理JDBC事务  
            transaction = session.beginTransaction;  
            try {  
                result = callback.doInTransaction(conn);  
            }  
            catch (RuntimeException ex) {  
                doRollback(session, transaction);  
                throw ex;  
            }  
            catch (Error err) {  
                doRollback(session, transaction);  
                throw err;  
            }  
            //如果数据库操作过程中没有发生异常则提交事务  
            transaction.commit;  
        } catch (WorkflowException e) {  
            logger.error("数据库操作失败事务回滚也失败!");  
            throw e;  
        } catch (RuntimeException ex) {  
            logger.error("数据库操作失败事务被回滚!");  
            throw ex;  
        } catch (Error err) {  
            logger.error("数据库操作失败事务被回滚!");  
            throw err;  
        } finally {  
            // 将session和当前线程解除绑定  
            TransactionSynchronizationManager.unbindResource(sessionFactory);  
            doClose(session);  
        }  
         result;  
    }  
 
    protected Session getSession(SessionFactory sessionFactory) {  
        Session session = SessionFactoryUtils.getSession(sessionFactory, true);  
        FlushMode flushMode = getFlushMode;  
         (flushMode != null) {  
            session.FlushMode(flushMode);  
        }  
         session;  
    }  
 
    private void doRollback(Session session, Transaction transaction) {  
        logger.debug("数据库操作异常开始回滚事务");  
        try {  
            transaction.rollback;  
            logger.debug("回滚事务成功!");  
        }  
        catch (Exception e) {  
            logger.error("回滚事务失败!");  
            throw  WorkflowException("回滚事务失败!");  
        } finally {  
            session.clear;  
        }  
    }  
 
    private void doClose(Session session) {  
        logger.debug("开始关闭连接");  
        try {  
            session.close;  
        }  
        catch (Exception e) {  
            logger.error("关闭连接失败!");  
            throw  WorkflowException("关闭连接失败!");  
        }  
    }  
 
    public FlushMode getFlushMode {  
         flushMode;  
    }  
 
    public void FlushMode(FlushMode flushMode) {  
        this.flushMode = flushMode;  
    }  
}  
public erface TransactionCallback {  
 
    Object doInTransaction(Connection conn);  
}伪代码:  
    public void methodA{  
        TransactionTemplate transactionTemplate= TransactionTemplate;  
        transactionTemplate.execute( TransactionCallback{  
            public Object doInTransaction(Connection conn) {  
                //客户代码  
                client.method1("1");  
                //我们代码 直接使用  
                our.method2;  
                //客户代码  
                client.method3("l");  
                 null;    
            }  
        });  
    } 


Tags:  spring和hibernate springhibernate hibernate与jdbc hibernatejdbc

延伸阅读

最新评论

发表评论