目的:使用HibernateTemplate执行execute(new HibernateCallback())方法,从HibernateCallback中得到session,在此session中做多个操作,并希望这些操作位于同一个事务中。
如果你这样写(1):

public static void main(String ss[])
{

CtxUtil.getBaseManager().getHibernateTemplate().execute(new HibernateCallback()
{

public Object doInHibernate(Session session) throws HibernateException, SQLException
{
// 保存stu1
Student stu1 = new Student();
stu1.setName("aaaa");// 在数据库中,name字段不允许为null
session.save(stu1);
session.flush();//实际上,如果不是程序员"手痒"来调用这个flush(),HibernateTemplate中session的事务处理还是很方便的

Student stu2 = new Student();
session.save(stu2);// 没有设置name字段,预期会报出例外
session.flush();
return null;
}
});

} 你期望spring在执行完execute回调后,在关闭session的时候提交事务,想法是很好的,但spring并不会这么做.让我们来看看在 Hibernate的源代码中,session.beginTransation()做了什么事。看如下代码(2):

public Transaction beginTransaction() throws HibernateException
{
errorIfClosed();

if ( rootSession != null )
{
// todo : should seriously consider not allowing a txn to begin from a child session
// can always route the request to the root session
log.warn( "Transaction started on non-root session" );
}
Transaction result = getTransaction();
result.begin();
return result;
}这个方法中的result是一个org.hibernate.transaction.JDBCTransaction实例,而方法中的getTransaction()方法源代码为(3):

public Transaction getTransaction() throws HibernateException
{

if (hibernateTransaction==null)
{
log.error(owner.getFactory().getSettings()
.getTransactionFactory().getClass());
hibernateTransaction = owner.getFactory().getSettings()
.getTransactionFactory()
.createTransaction( this, owner );
}
return hibernateTransaction;
}再次追踪,owner.getFactory().getSettings() .getTransactionFactory()的createTransaction()方法源代码如下(4):
public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)

throws HibernateException
{
return new JDBCTransaction( jdbcContext, transactionContext );
}它返回了一个JDBCTransaction,没什么特别的。
在代码2中,执行了result.begin(),其实也就是JDBCTransaction实例的begin()方法,来看看(5):

public void begin() throws HibernateException
{

if (begun)
{
return;
}

if (commitFailed)
{
throw new TransactionException("cannot re-start transaction after failed commit");
}
log.debug("begin");

try
{
toggleAutoCommit = jdbcContext.connection().getAutoCommit();

if (log.isDebugEnabled())
{
log.debug("current autocommit status: " + toggleAutoCommit);
}

if (toggleAutoCommit)
{
log.debug("disabling autocommit");
jdbcContext.connection().setAutoCommit(false);//把自动提交设为了false
}

} catch (SQLException e)
{
log.error("JDBC begin failed", e);
throw new TransactionException("JDBC begin failed: ", e);
}
callback = jdbcContext.registerCallbackIfNecessary();
begun = true;
committed = false;
rolledBack = false;


if (timeout > 0)
{
jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);
}

jdbcContext.afterTransactionBegin(this);
}在直接使用Hibernate时,要在事务结束的时候,写上一句:tx.commit(),这个commit()的源码为:

public void commit() throws HibernateException
{

if (!begun)
{
throw new TransactionException("Transaction not successfully started");
}

log.debug("commit");


if (!transactionContext.isFlushModeNever() && callback)
{
transactionContext.managedFlush(); // if an exception occurs during
// flush, user must call
// rollback()
}

notifyLocalSynchsBeforeTransactionCompletion();

if (callback)
{
jdbcContext.beforeTransactionCompletion(this);
}


try
{
commitAndResetAutoCommit();//重点代码,它的作用是提交事务,并把connection的autocommit属性恢复为true
log.debug("committed JDBC Connection");
committed = true;

if (callback)
{
jdbcContext.afterTransactionCompletion(true, this);
}
notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_COMMITTED);

} catch (SQLException e)
{
log.error("JDBC commit failed", e);
commitFailed = true;

if (callback)
{
jdbcContext.afterTransactionCompletion(false, this);
}
notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_UNKNOWN);
throw new TransactionException("JDBC commit failed", e);

} finally
{
closeIfRequired();
}
}上面代码中,commitAndResetAutoCommit()方法的源码如下:

private void commitAndResetAutoCommit() throws SQLException
{

try
{
jdbcContext.connection().commit();//这段不用说也能理解了

} finally
{
toggleAutoCommit();//这段的作用是恢复connection的autocommit属性为true
}
}上述代码的toggleAutoCommit()源代码如下:
分享到:
相关推荐
`HibernateTemplate`提供了多种事务处理机制,可以轻松集成到业务逻辑中,确保数据的一致性和完整性。 ```java hibernateTemplate.execute(new HibernateCallback() { public Void doInHibernate(Session ...
以下是一段示例代码,旨在演示如何使用`HibernateTemplate`进行多个数据库操作,并确保所有操作处于同一事务中: ```java public static void main(String[] args) { CtxUtil.getBaseManager()....
在这个例子中,开发者试图保存两个学生对象(stu1和stu2),期望它们在一个事务中完成。然而,由于`HibernateTemplate`的默认行为,当在`doInHibernate`内部调用`session.flush()`时,事务实际上已经被提交。这意味...
List list = hibernateTemplate.execute(new HibernateCallback() { @Override public List doInHibernate(Session session) throws HibernateException, SQLException { Query query = session.createQuery...
6. **Callback机制**:通过HibernateCallback接口,可以在Hibernate Session内部执行自定义操作,保持事务的一致性。 **三、使用示例** 在使用HibernateTemplate之前,需要配置SessionFactory,并将其注入到...
`HibernateTemplate`在事务管理、异常转换等方面提供了很多便利,而`HibernateDaoSupport`是一个抽象类,它的目的是为DAO提供对`HibernateTemplate`的便捷访问。 当我们在DAO中继承`HibernateDaoSupport`时,可以...
Spring通过提供一系列的DAO抽象类,如HibernateDaoSupport,HibernateTemplate以及HibernateCallBack,使得开发者可以更方便地实现DAO组件。这些抽象类作为DAO实现类的基类,降低了开发难度,确保了代码的一致性和可...
- **Hibernate**:Spring通过HibernateTemplate和HibernateCallback接口,提供了对Hibernate的集成,使得我们可以利用Spring的DI和AOP来管理SessionFactory和Session。 - **MyBatis**:Spring支持MyBatis的...
HibernateTemplate支持`HibernateCallback`接口,允许在回调方法中执行自定义的Hibernate操作。这提供了一种方式在事务内部执行复杂操作,例如批量处理或自定义查询。开发者可以在实现`doInHibernate(Session ...
通常,程序中采用实现HibernateCallback的匿名内部类来获取HibernateCallback的实例,方法doInHibernate()就是Spring执行的持久化操作。 24.3 Spring对Hibernate的简化 24.3.5 HibernateDaoSupport Spring为与...
此外,Spring还提供了HibernateTemplate和HibernateCallback接口,使得事务管理变得更加简单。在`applicationContext.xml`中,我们需要配置Hibernate的相关bean,如SessionFactory、DataSource等。 对于Struts和...
在Spring框架中整合Hibernate是为了提供更高效、便捷的数据访问和事务管理能力。Spring整合Hibernate主要有以下三种方式: 1. **使用HibernateTemplate** HibernateTemplate是Spring早期为了简化Hibernate操作而...
此外,`HibernateTemplate`还支持`HibernateCallback`接口,允许开发者在回调方法`doInHibernate(Session session)`中使用原生的Hibernate API,以应对更复杂的数据访问需求。这种方法确保了灵活性,即使在Spring的...
AOP即面向切面编程,它允许将横切关注点(如日志、事务管理等)从业务逻辑中分离出来,通过声明式的方式动态地添加到程序中。 11. Spring AOP配置与应用: Spring AOP配置同样支持XML和注解方式。注解方式通过定义...
在上面的代码中,我们使用 `HibernateCallback` 接口来执行原生 SQL 语句,该接口提供了一个 `doInHibernate()` 方法,该方法将在 Hibernate 事务中执行。我们可以在该方法中执行原生 SQL 语句,并使用 `Connection`...
4. 使用`HibernateTemplate`或`HibernateCallback`接口来简化数据库操作。 **Spring与Struts的整合** 整合Spring和Struts有三种常见方式: 1. **Spring不管理Action(使用Spring的ActionSupport类整合Struts)** ...
return (List) hibernateTemplate.execute(new HibernateCallback<List<Person>>() { @Override public List<Person> doInHibernate(Session session) throws HibernateException { Criteria criteria = session...
`execute`方法会确保在事务中执行回调方法,这样可以保证数据库操作的原子性。`exposeNativeSession`参数决定是否暴露底层的JDBC Session给回调方法,这在需要直接使用原生SQL或者处理特定事务管理时非常有用。 总...
2. **ORM集成**:Spring通过`HibernateTemplate`和`HibernateCallback`支持Hibernate,简化了事务管理和对象关系映射。同样,对于MyBatis,Spring提供`SqlSessionFactoryBean`和`SqlSessionTemplate`来整合MyBatis,...