解决的办法是重写DatabaseConfig.PROPERTY_METADATA_HANDLER中的getPrimaryKeys方法,当遇到没有主键的表,就把所有表字段都当成主键。在提供IDatabaseTester是就要把该Handler设置进去。
package org.iata.ios.test.utils; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.dbunit.IDatabaseTester; import org.dbunit.JdbcDatabaseTester; import org.dbunit.database.DatabaseConfig; import org.dbunit.database.DefaultMetadataHandler; import org.dbunit.database.IDatabaseConnection; import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleRowSource; public class DBUnitHelper { private static IDatabaseTester tester; private DBUnitHelper() { } private static IDatabaseTester newDatabaseTester() throws Exception { JdbcDatabaseTester jdbcDatabaseTester = new JdbcDatabaseTester( Configuration.getValue("database.connection.driver_class"), Configuration.getValue("database.connection.url"), Configuration.getValue("database.connection.username"), Configuration.getValue("database.connection.password")) { public IDatabaseConnection getConnection() throws Exception { IDatabaseConnection connection = super.getConnection(); connection.getConfig().setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MyDefaultMetadataHandler()); return connection; } }; return jdbcDatabaseTester; } private static IDatabaseTester getDatabaseTester() throws Exception { if (tester == null) { tester = newDatabaseTester(); } return tester; } public static void executeBeforeOperations(List<DataSetOperation> list) throws Exception { final IDatabaseTester databaseTester = getDatabaseTester(); if (databaseTester != null) { for (DataSetOperation dso : list) { databaseTester.setSetUpOperation(dso.getOperation()); databaseTester.setDataSet(dso.getDataSet()); databaseTester.onSetup(); } } } public static void executeAfterOperations(List<DataSetOperation> list) throws Exception { final IDatabaseTester databaseTester = getDatabaseTester(); if (databaseTester != null) { for (DataSetOperation dso : list) { databaseTester.setTearDownOperation(dso.getOperation()); databaseTester.setDataSet(dso.getDataSet()); databaseTester.onTearDown(); } } } static class MyDefaultMetadataHandler extends DefaultMetadataHandler { public ResultSet getPrimaryKeys(DatabaseMetaData metaData, String schemaName, String tableName) throws SQLException { ResultSet resultSet = super.getPrimaryKeys(metaData, schemaName, tableName); if (resultSet.next()) { resultSet.close(); resultSet = super.getPrimaryKeys(metaData, schemaName, tableName); } else { resultSet.close(); ResultSet pkRS = super.getColumns(metaData, schemaName, tableName); List<Object[]> list = new ArrayList<Object[]>(); SimpleResultSet simpleResultSet = new SimpleResultSet(new MySimpleRowSource(list)); int i = 1; boolean isInit = false; try { while (pkRS.next()) { if (!isInit) { ResultSetMetaData md = pkRS.getMetaData(); simpleResultSet.addColumn("TABLE_CAT", md.getColumnType(1), md.getPrecision(1), md.getScale(1)); simpleResultSet.addColumn("TABLE_SCHEM", md.getColumnType(2), md.getPrecision(2), md.getScale(2)); simpleResultSet.addColumn("TABLE_NAME", md.getColumnType(3), md.getPrecision(3), md.getScale(3)); simpleResultSet.addColumn("COLUMN_NAME", md.getColumnType(4), md.getPrecision(4), md.getScale(4)); simpleResultSet.addColumn("KEY_SEQ", md.getColumnType(5), md.getPrecision(5), md.getScale(5)); simpleResultSet.addColumn("COLUMN_NAME", md.getColumnType(4), md.getPrecision(4), md.getScale(4)); isInit = true; } Object[] objs = new Object[] { pkRS.getString(1), pkRS.getString(2), pkRS.getString(3), pkRS.getString(4), i++, pkRS.getString(4) }; list.add(objs); // String name = resultSet.getString(4); // int sequence = resultSet.getInt(5); // list.add(new PrimaryKeyData(name, sequence)); } } finally { pkRS.close(); } resultSet = simpleResultSet; } return resultSet; } } static class MySimpleRowSource implements SimpleRowSource { List<Object[]> datas = new ArrayList<Object[]>(); int current; public MySimpleRowSource(List<Object[]> datas) { this.datas = datas; current = 0; } public Object[] readRow() throws SQLException { return datas.size() > current ? datas.get(current++) : null; } public void close() { datas.clear(); } public void reset() throws SQLException { current = 0; } } }