事务、会话和工厂类——MapperFactory
我们应该在何处获取“Mapper”的实例呢?我们仍然需要一个核心类来完成iBATIS的配置和控制。这个核心类的名称尚在争论之中,但是我们不妨先叫它MapperFactory。
通常情况下,MapperFactory负责构建事务和映射类的实例。而MapperFactory本身将由某个配置类来构建。
MapperFactory factory = someConfiguration.buildMapperFactory();
EmployeeMapper employeeMapper = factory.getMapper (EmployeeMapper.class);
对于这种方式是不是会使事情变得简单...或许会吧!至于事务,Clinton是这样说的:“会话的概念应该和事务的进行合并。在iBATIS中,会话和事务很多时候是一致甚至是一样的。但是它们因为一些人为的架构方面的原因而被分开了。会话或许能够完成不少任务,但是其中的80%并不适合用会话来解决。同样的,批处理操作也从事务中分离出来,因为事务在提供批处理功能是往往会导致令人生厌的try/finally的多重嵌套。因此在我们发现真实的需求之前应该尽量避免这些。”。
iBATIS或者其他第三方库及容器都可以进行事务处理。目前,事务的处理是由SqlMapClient实例中的ThreadLocal实例来处理的。因为这种处理方法,我们配到了不少问题。不是出于技术的原因而是因为代码更加清晰,我们可以使用以下的方法:
Transaction tx = factory.startTransaction();
try
{
// do work
tx.commit();
}
finally
{
tx.end();
}
批处理操作可以简单地通过启动支持批处理操作的事务来进行:
Transaction tx = factory.startBatch();
try
{
// do work
// balk executes current batch immediately, returns total rows updated
// (balks on non-batched transactions)
int totalRowCount = tx.flush();
// commit executes batch too, returns total rows updated and commits
totalRowCount = tx.commit();
}
finally
{
tx.end();
}
与现在的事务的API类似,我们对事务的隔离级别以及其他选项提供支持。
Transaction tx = factory.startTransaction(isolationLevel);
try
{
// do work
tx.commit();
}
finally
{
tx.end();
}
如果第三方的库提供了事务处理的支持,那么受托管理的连接对象可以作为参数传入:
// Can be handled by encapsulating framework (e.g. Spring)
Transaction tx = factory.useConnection(conn);
try
{
//...do work...
tx.flush(); // executes batched updates immediately
// commit simply calls commit on the connection
// if local commits are allowed, otherwise it is ignored.
tx.commit();
}
finally
{
tx.end(); // Can also be handled by encapsulating framework (e.g. Spring)
}
总之,这样的API十分的简洁,而且易于与诸如Spring这样的第三方框架集成。MapperFactory可以被注入到需要事务管理、批处理和隔离级别的Spring的DAO对象中。为了进一步进行必要的分离,我们可以将事务管理功能从MapperFactory中分离出来,甚至于允许开发者定义自己的事务管理接口,同时将事务管理的功能绑定到类中(这样提供了更加松耦合的架构)。