org.dbunit.operation.RefreshOperation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dbunit Show documentation
Show all versions of dbunit Show documentation
dbUnit is a JUnit extension (also usable from Ant and Maven) targeted for database-driven projects that, among other things, puts your database into a known state between test runs. This is an excellent way to avoid the myriad of problems that can occur when one test case corrupts the database and causes subsequent tests to fail or exacerbate the damage.
/*
*
* The DbUnit Database Testing Framework
* Copyright (C)2002-2004, DbUnit.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package org.dbunit.operation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.statement.IPreparedBatchStatement;
import org.dbunit.database.statement.SimplePreparedStatement;
import org.dbunit.dataset.Column;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.ITableIterator;
import org.dbunit.dataset.ITableMetaData;
import org.dbunit.dataset.NoPrimaryKeyException;
import org.dbunit.dataset.RowOutOfBoundsException;
import org.dbunit.dataset.datatype.DataType;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.BitSet;
/**
* This operation literally refreshes dataset contents into the database. This
* means that data of existing rows is updated and non-existing row get
* inserted. Any rows which exist in the database but not in dataset stay
* unaffected.
*
* @author Manuel Laflamme
* @version $Revision$
* @since Feb 19, 2002
*/
public class RefreshOperation extends AbstractOperation
{
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(RefreshOperation.class);
private final InsertOperation _insertOperation;
private final UpdateOperation _updateOperation;
RefreshOperation()
{
_insertOperation = (InsertOperation)DatabaseOperation.INSERT;
_updateOperation = (UpdateOperation)DatabaseOperation.UPDATE;
}
private boolean isEmpty(ITable table) throws DataSetException
{
return AbstractBatchOperation.isEmpty(table);
}
////////////////////////////////////////////////////////////////////////////
// DatabaseOperation class
public void execute(IDatabaseConnection connection, IDataSet dataSet)
throws DatabaseUnitException, SQLException
{
logger.debug("execute(connection={}, dataSet) - start", connection);
// for each table
ITableIterator iterator = dataSet.iterator();
while (iterator.next())
{
ITable table = iterator.getTable();
String tableName=table.getTableMetaData().getTableName();
logger.trace("execute: processing table='{}'", tableName);
// Do not process empty table
if (isEmpty(table))
{
continue;
}
ITableMetaData metaData = getOperationMetaData(connection,
table.getTableMetaData());
RowOperation updateRowOperation = createUpdateOperation(connection,
metaData);
RowOperation insertRowOperation = new InsertRowOperation(connection,
metaData);
try
{
// refresh all rows
for (int i = 0; ; i++)
{
if (!updateRowOperation.execute(table, i))
{
insertRowOperation.execute(table, i);
}
}
}
catch (RowOutOfBoundsException e)
{
// This exception occurs when records are exhausted
// and we reach the end of the table. Ignore this error.
// end of table
}
catch (SQLException e)
{
final String msg =
"Exception processing table name='" + tableName + "'";
throw new DatabaseUnitException(msg, e);
}
finally
{
// cleanup
updateRowOperation.close();
insertRowOperation.close();
}
}
}
private RowOperation createUpdateOperation(IDatabaseConnection connection,
ITableMetaData metaData)
throws DataSetException, SQLException
{
logger.debug("createUpdateOperation(connection={}, metaData={}) - start", connection, metaData);
// update only if columns are not all primary keys
if (metaData.getColumns().length > metaData.getPrimaryKeys().length)
{
return new UpdateRowOperation(connection, metaData);
}
// otherwise, operation only verify if row exist
return new RowExistOperation(connection, metaData);
}
/**
* This class represents a operation executed on a single table row.
*/
class RowOperation
{
/**
* Logger for this class
*/
private final Logger logger = LoggerFactory.getLogger(RowOperation.class);
protected IPreparedBatchStatement _statement;
protected OperationData _operationData;
protected BitSet _ignoreMapping;
/**
* Execute this operation on the sepcified table row.
* @return true
if operation have been executed on the row.
*/
public boolean execute(ITable table, int row)
throws DataSetException, SQLException
{
logger.debug("execute(table={}, row={}) - start", table, String.valueOf(row));
Column[] columns = _operationData.getColumns();
for (int i = 0; i < columns.length; i++)
{
// Bind value only if not in ignore mapping
if (_ignoreMapping == null || !_ignoreMapping.get(i))
{
Object value = table.getValue(row, columns[i].getColumnName());
_statement.addValue(value, columns[i].getDataType());
}
}
_statement.addBatch();
int result = _statement.executeBatch();
_statement.clearBatch();
return result == 1;
}
/**
* Cleanup this operation state.
*/
public void close() throws SQLException
{
logger.debug("close() - start");
if (_statement != null)
{
_statement.close();
}
}
}
/**
* Insert row operation.
*/
private class InsertRowOperation extends RowOperation
{
/**
* Logger for this class
*/
private final Logger logger = LoggerFactory.getLogger(InsertRowOperation.class);
private IDatabaseConnection _connection;
private ITableMetaData _metaData;
public InsertRowOperation(IDatabaseConnection connection,
ITableMetaData metaData)
throws DataSetException, SQLException
{
_connection = connection;
_metaData = metaData;
}
public boolean execute(ITable table, int row)
throws DataSetException, SQLException
{
logger.debug("execute(table={}, row={}) - start", table, String.valueOf(row));
// If current row has a different ignore value mapping than
// previous one, we generate a new statement
if (_ignoreMapping == null ||
!_insertOperation.equalsIgnoreMapping(_ignoreMapping, table, row))
{
// Execute and close previous statement
if (_statement != null)
{
_statement.close();
}
_ignoreMapping = _insertOperation.getIgnoreMapping(table, row);
_operationData = _insertOperation.getOperationData(_metaData,
_ignoreMapping, _connection);
_statement = new SimplePreparedStatement(_operationData.getSql(),
_connection.getConnection());
}
return super.execute(table, row);
}
}
/**
* Update row operation.
*/
private class UpdateRowOperation extends RowOperation
{
PreparedStatement _countStatement;
public UpdateRowOperation(IDatabaseConnection connection,
ITableMetaData metaData)
throws DataSetException, SQLException
{
// setup update statement
_operationData = _updateOperation.getOperationData(
metaData, null, connection);
_statement = new SimplePreparedStatement(_operationData.getSql(),
connection.getConnection());
}
}
/**
* This operation verify if a row exists in the database.
*/
private class RowExistOperation extends RowOperation
{
/**
* Logger for this class
*/
private final Logger logger = LoggerFactory.getLogger(RowExistOperation.class);
PreparedStatement _countStatement;
public RowExistOperation(IDatabaseConnection connection,
ITableMetaData metaData)
throws DataSetException, SQLException
{
// setup select count statement
_operationData = getSelectCountData(metaData, connection);
_countStatement = connection.getConnection().prepareStatement(
_operationData.getSql());
}
private OperationData getSelectCountData(
ITableMetaData metaData, IDatabaseConnection connection) throws DataSetException
{
logger.debug("getSelectCountData(metaData={}, connection={}) - start", metaData, connection);
Column[] primaryKeys = metaData.getPrimaryKeys();
// cannot construct where clause if no primary key
if (primaryKeys.length == 0)
{
throw new NoPrimaryKeyException(metaData.getTableName());
}
// select count
StringBuffer sqlBuffer = new StringBuffer(128);
sqlBuffer.append("select COUNT(*) from ");
sqlBuffer.append(getQualifiedName(connection.getSchema(), metaData.getTableName(), connection));
// where
sqlBuffer.append(" where ");
for (int i = 0; i < primaryKeys.length; i++)
{
Column column = primaryKeys[i];
if (i > 0)
{
sqlBuffer.append(" and ");
}
sqlBuffer.append(getQualifiedName(null, column.getColumnName(), connection));
sqlBuffer.append(" = ?");
}
return new OperationData(sqlBuffer.toString(), primaryKeys);
}
////////////////////////////////////////////////////////////////////////
// RowOperation class
/**
* Verify if the specified table row exists in the database.
* @return true
if row exists.
*/
public boolean execute(ITable table, int row)
throws DataSetException, SQLException
{
logger.debug("execute(table={}, row={}) - start", table, String.valueOf(row));
Column[] columns = _operationData.getColumns();
for (int i = 0; i < columns.length; i++)
{
Object value = table.getValue(row, columns[i].getColumnName());
DataType dataType = columns[i].getDataType();
dataType.setSqlValue(value, i + 1, _countStatement);
}
ResultSet resultSet = _countStatement.executeQuery();
try
{
resultSet.next();
return resultSet.getInt(1) > 0;
}
finally
{
resultSet.close();
}
}
public void close() throws SQLException
{
logger.debug("close() - start");
_countStatement.close();
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy