Question

I want to reset the Database AND sequences after each test in Java+DBUnit/.

I've seen this question but doesn't have the code solution I am struggling to get. How to use Oracle Sequence Numbers in DBUnit?

Was it helpful?

Solution

I've found the answer, it was in the Official Documentation. It was as easy as in the dataset you are using to prepare the database, add a reset_sequences attribute with a list of the ones you want to reset.

 <?xml version='1.0' encoding='UTF-8'?>
    <dataset reset_sequences="emp_seq, dept_seq">
        <emp empno="1" ename="Scott" deptno="10" job="project manager" />
        ....
    </dataset>

This solution is not working perfectly, as it didn't really reset the sequence, only simulates the reset on the inserted rows. If you want to effectively reset it, you should execute some commands. I've extended the DatabaseOperation for that purpose with this class.

public static final DatabaseOperation SEQUENCE_RESETTER_POSTGRES = new DatabaseOperation() {
    @Override
    public void execute(IDatabaseConnection connection, IDataSet dataSet)
            throws DatabaseUnitException, SQLException {
        String[] tables = dataSet.getTableNames();
        Statement statement = connection.getConnection().createStatement();
        for (String table : tables) {
            int startWith = dataSet.getTable(table).getRowCount() + 1;
            statement.execute("alter sequence " + table + "_PK_SEQ RESTART WITH "+ startWith);

        }
    }
};

public static final DatabaseOperation SEQUENCE_RESETTER_ORACLE = new DatabaseOperation() {
    @Override
    public void execute(IDatabaseConnection connection, IDataSet dataSet)
            throws DatabaseUnitException, SQLException {
        String[] tables = dataSet.getTableNames();
        Statement statement = connection.getConnection().createStatement();
        for (String table : tables) {
            int startWith = dataSet.getTable(table).getRowCount() + 1;
            statement.execute("drop sequence " + table + "_PK_SEQ if exists");
            statement.execute("create sequence " + table + "_PK_SEQ START WITH " + startWith);
        }
    }
};

OTHER TIPS

I've tested the solution provided by @Chexpir, and here is an improved/cleaner way (PostgreSQL implementation) - Also note that the sequence is reset to 1 (instead of retrieving the row count)

public class ResetSequenceOperationDecorator extends DatabaseOperation {

    private DatabaseOperation decoree;

    public ResetSequenceOperationDecorator(DatabaseOperation decoree) {
         this.decoree = decoree;
     }

     @Override
     public void execute(IDatabaseConnection connection, IDataSet dataSet) throws DatabaseUnitException, SQLException {
         String[] tables = dataSet.getTableNames();
         Statement statement = connection.getConnection().createStatement();
         for (String table : tables) {
             try {
                 statement.execute("ALTER SEQUENCE " + table + "_id_seq RESTART WITH 1");
             }
             // Don't care because the sequence does not appear to exist (but catch it silently)
             catch(SQLException ex) {
             }
         }
         decoree.execute(connection, dataSet);
     }
}

And in your DatabaseTestCase:

public abstract class AbstractDBTestCase extends DataSourceBasedDBTestCase {

    @Override
    protected DatabaseOperation getTearDownOperation() throws Exception {
        return new ResetSequenceOperationDecorator(DatabaseOperation.DELETE_ALL);
    }
}

Can you please check the below link if anyway it helps you.

How to revert the database back to the initial state using dbUnit?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top