【发布时间】:2014-01-03 15:41:38
【问题描述】:
我想在 Java+DBUnit/ 中每次测试后重置数据库 AND 序列。
我已经看到了这个问题,但没有我正在努力获得的代码解决方案。 How to use Oracle Sequence Numbers in DBUnit?
【问题讨论】:
-
你用的是什么数据库?
-
我是多数据库,所以我必须支持Oracle、Posgres和Derby。
我想在 Java+DBUnit/ 中每次测试后重置数据库 AND 序列。
我已经看到了这个问题,但没有我正在努力获得的代码解决方案。 How to use Oracle Sequence Numbers in DBUnit?
【问题讨论】:
我找到了答案,它在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);
}
}
};
【讨论】:
我已经测试了@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);
}
}
【讨论】:
如果对您有帮助,请查看以下链接。
How to revert the database back to the initial state using dbUnit?
【讨论】: