【问题标题】:Reset sequence in DBUnit?DBUnit 中的重置序列?
【发布时间】:2014-01-03 15:41:38
【问题描述】:

我想在 Java+DBUnit/ 中每次测试后重置数据库 AND 序列。

我已经看到了这个问题,但没有我正在努力获得的代码解决方案。 How to use Oracle Sequence Numbers in DBUnit?

【问题讨论】:

  • 你用的是什么数据库?
  • 我是多数据库,所以我必须支持Oracle、Posgres和Derby。

标签: java dbunit


【解决方案1】:

我找到了答案,它在Official Documentation 中。就像在您用于准备数据库的数据集中一样简单,添加一个 reset_sequences 属性以及您要重置的列表。

 <?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>

此解决方案无法完美运行,因为它并没有真正重置序列,只是模拟插入行的重置。如果你想有效地重置它,你应该执行一些命令。为此,我使用此类扩展了 DatabaseOperation。

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);
        }
    }
};

【讨论】:

    【解决方案2】:

    我已经测试了@Chexpir 提供的解决方案,这是一种改进/更清洁的方法(PostgreSQL 实现)- 另请注意,序列被重置为 1(而不是检索行数)

    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);
         }
    }
    

    在你的 DatabaseTestCase 中:

    public abstract class AbstractDBTestCase extends DataSourceBasedDBTestCase {
    
        @Override
        protected DatabaseOperation getTearDownOperation() throws Exception {
            return new ResetSequenceOperationDecorator(DatabaseOperation.DELETE_ALL);
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果对您有帮助,请查看以下链接。

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

      【讨论】:

      • 谢谢,但使用 CLEAN_INSERT 对我没有帮助,我给出的答案是好的 :-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-03
      • 2020-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-30
      相关资源
      最近更新 更多