因为所有的IDatabaseTester实现(包括DefaultDatabaseTester)都继承自AbatractDatabaseTester,这个抽象类有一个统一的执行数据库操作的方法executeOperation,原代码如下:
private void executeOperation(DatabaseOperation operation) throws Exception
{
logger.debug("executeOperation(operation={})- start", operation);
if(operation != DatabaseOperation.NONE ){
// IDatabaseTester 的 getConnection 方法,不是重载的那个。
IDatabaseConnection connection = getConnection();
try{
operation.execute(connection, getDataSet() );
}
finally{
closeConnection(connection);
}
}
}
我们看到每执行完一次操作,数据库连接都会被关闭,所以如果继承DefaultDatabaseTester,将导致只能执行一次数据库操作。
如果希望在一个TestCase里执行两次操作,我们可以使用另一个基类
DBTestCase类
如上面所看到的,问题出在DatabaseTestCase的newDatabaseTester方法返回了一个无法重复利用的DefaultDatabaseTester实例,所以DBTestCase的newDatabaseTester方法代码变更如下:
protected IDatabaseTester newDatabaseTester() throws Exception {
return new PropertiesBasedJdbcDatabaseTester();
}
它用来生成实例的是 PropertiesBasedJdbcDatabaseTester 类,而不是 DefaultDatabaseTester 。这个类的父类 JdbcDatabaseTester(也继承自 AbstractDatabaseTester)的 getConnection 方法:
public IDatabaseConnection getConnection() throws Exception
{
logger.debug("getConnection() - start");
if(!initialized ){
// 注意这个方法,等一下详解
initialize();
}
assertNotNullNorEmpty("connectionUrl", connectionUrl);
Connection conn = null;
if(username == null && password == null ){
conn = DriverManager.getConnection(connectionUrl);
}else{
Conn = DriverManager.getConnection(connectionUrl,username,password);
}
return new DatabaseConnection( conn, getSchema() );
}
可以看到每次调用这个方法,都会新建一个连接,而不是简单的返回我们重载的 getConnection 中返回的连接的引用。这样避免了 DefaultDatabaseTester 仅仅是简单返回之前的连接而倒置的问题。不过这也意味着用 DBTestCase 不用我们自己去重载 getConnection 了,因为 DBTestCase 已经实现了这个方法(DatabaseTestCase没有实现):
protected IDatabaseConnection getConnection() throws Exception {
logger.debug("getConnection() - start");
final IDatabaseTester databaseTester = getDatabaseTester();
assertNotNull( "DatabaseTester is not set",databaseTester);
return databaseTester.getConnection();
}
我们看到DBTestCase的getConnection简单的把这个方法转给JdbcDatabaseTester(IDatabaseTester) 的getConnection。而JdbcDatabaseTester的实现我们在前面已经看到了。