昨天还在用Torque,今天听说Hibernate更好,明天说不准又有更好的持久层工具...
如何使应用程序不变化的情况下选择不同的持久层呢?
看看Finetix LLC的资深顾问Charles Chan 给我们现身说法。
Charles Chan
在文章 Object-Relational Mapping with Apache Jakarta OJB
中介绍了Apache OJB的使用,并在文章附录中提到一种屏蔽不同持久层的设计思路,他采用了工厂方法模式(Factory Method),并通过实例Apache OJB来说明他的设计。
这个设计有两个产品,一个是PersistenceManager,另一个是Transaction 。
OJBPersistenceManager和OJBTransaction 分别是两个产品的实现。
It is often desirable to decouple your application from the specifics of a persistence framework, so that you can easily switch frameworks in the future. I recommend creating custom PersistenceManager and Transaction classes for this purpose. For example:
Example
13
: PersistenceManager and Transaction Interfaces
/** */
/**
* The abstract base class for all PersistenceManager. It provides
* method to persist and object and to obtain the current
* transaction.
*/
public
abstract
class
PersistenceManager
{
public
static
PersistenceManager getInstance()
{
return
new
OJBPersistenceManager();
}
public
abstract
void
makePersistent(Object o)
throws
PersistenceException;
public
abstract
Transaction currentTransaction()
throws
PersistenceException;
}
/** */
/**
* A Transaction interface. It provides minimal support for
* beginning, committing, and rolling back a transaction.
*/
public
interface
Transaction
{
public
void
begin()
throws
PersistenceException;
public
void
commit()
throws
PersistenceException;
public
void
rollback()
throws
PersistenceException;
}
/** */
/**
* An OJB specific implementation of the PersistenceManager
* class.
*/
public
class
OJBPersistenceManager
extends
PersistenceManager
{
private
PersistenceBroker broker
=
null
;
public
OJBPersistenceManager()
{
broker
=
PersistenceBrokerFactory.defaultPersistenceBroker();
}
public
void
makePersistent(Object o)
throws
PersistenceException
{
try
{
broker.store(o);
}
catch
(PersistenceBrokerException e)
{
//
rethrow PersistenceException
}
}
public
Transaction currentTransaction()
throws
PersistenceException
{
return
new
OJBTransaction(broker);
}
}
/** */
/**
* An OJB specific implementation of the Transaction
* interface.
*/
public
class
OJBTransaction
implements
Transaction
{
private
PersistenceBroker broker
=
null
;
public
OJBTransaction(PersistenceBroker broker)
{
this
.broker
=
broker;
}
public
void
begin()
throws
PersistenceException
{
try
{
broker.beginTransaction();
}
catch
(TransactionAbortedException e)
{
//
rethrow PersistenceException
}
catch
(TransactionInProgressException e)
{
//
rethrow PersistenceException
}
}
public
void
commit()
throws
PersistenceException
{
try
{
broker.commitTransaction();
}
catch
(TransactionAbortedException e)
{
//
rethrow PersistenceException
}
catch
(TransactionNotInProgressException e)
{
//
rethrow PersistenceException
}
}
public
void
rollback()
throws
PersistenceException
{
try
{
broker.abortTransaction();
}
catch
(TransactionNotInProgressException e)
{
//
rethrow PersistenceException
}
}
}
After the above classes are created, it is very simple to convert the test application to use them:
下面是这个Factory的使用:
Example
14
: Example Using PersistenceManager and Transaction Interfaces
PersistenceManager pm
=
PersistenceManager.getInstance();
Transaction tx
=
pm.currentTransaction();
tx.begin();
Manager manager
=
newManager();
manager.setName(
"
John Smith
"
);
manager.setProjectNumber(
new
Integer(
10
));
pm.makePersistent(manager);
Employee employee
=
newEmployee();
employee.setName(
"
David Cosby
"
);
pm.makePersistent(employee);
tx.commit();
It looks surprisingly like JDO, doesn't it? With a little more effort, you can also hide the OJB query mechanism.
改进建议:
1. 改用抽象工厂方法, 一套持久层产品提供一个工厂,用于创建不同的产品(如:PersistenceManager,Transaction....)
2.考虑从不同的持久层产品中抽取一套通用的持久层接口