将 DbUnit 与没有主键的表一起使用
Posted
技术标签:
【中文标题】将 DbUnit 与没有主键的表一起使用【英文标题】:Using DbUnit with tables which do not have primary keys 【发布时间】:2012-02-26 05:04:36 【问题描述】:我正在尝试设置我的单元测试环境以使用 DbUnit。
我遇到了一些问题,因为我试图控制的表没有主键。我收到了org.dbunit.dataset.NoPrimaryKeyException
。
我已按照http://dbunit.wikidot.com/noprimarykeytable 此处的步骤操作,但我该如何使用:
connection.getConfig().setProperty("http://www.dbunit.org/properties/primaryKeyFilter", new MyPrimaryKeyFilter("A1"));
我的每张桌子?
例如,我有以下数据库:
CREATE TABLE `NO_PK1` (
`A1` int(11) NOT NULL,
`A2` varchar(50) default NULL
);
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<NO_PK1 A1="1" A2="Test1" />
<NO_PK1 A1="2" A2="Test2" />
<NO_PK1 A1="3" />
</dataset>
CREATE TABLE `NO_PK2` (
`B1` int(11) NOT NULL,
`B2` varchar(50) default NULL
);
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<NO_PK2 B1="1" B2="Test1" />
<NO_PK2 B1="2" B2="Test2" />
<NO_PK2 B1="3" />
</dataset>
CREATE TABLE `NO_PK3` (
`C1` int(11) NOT NULL,
`C2` varchar(50) default NULL
);
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<NO_PK3 C1="1" C2="Test1" />
<NO_PK3 C1="2" C2="Test2" />
<NO_PK3 C1="3" />
</dataset>
在这种情况下如何重写connection.getConfig().setProperty("http://www.dbunit.org/properties/primaryKeyFilter", new MyPrimaryKeyFilter("A1"));
?
非常感谢您的建议。
【问题讨论】:
【参考方案1】:您需要确保您的 MyPrimaryKeyFilter 处理架构中的所有表。在示例中,只有一个表,因此提供的简单过滤器类可以正常工作。在您的情况下,我可能会更改该类以获取包含表的 Map -> pk 列名映射:
class MyPrimaryKeyFilter implements IColumnFilter
private Map<String, String> pseudoKey = null;
MyPrimaryKeyFilter(Map<String, String> pseudoKey)
this.pseudoKey = pseudoKey;
public boolean accept(String tableName, Column column)
return column.getColumnName().equalsIgnoreCase(pseudoKey.get(tableName));
然后使用 NO_PK1 -> A1、NO_PK2 -> B1 和 NO_PK3 -> C1 条目设置地图。
【讨论】:
谢谢 slushi。这就说得通了。如果其中一张表有一个由多个字段组成的键怎么办? 我认为您可以将 Map 更改为 Mapreturn pseudoKey.get(tableName).contains(column.getColumnName());
?
我认为是这样,您可能需要稍微更改它以处理不区分大小写的问题。我会进行测试以查看 column.getColumnName() 返回的情况。或者您可以将 Set 中的所有内容以及 column.getColumnName() 中的值大写。【参考方案2】:
我遇到了同样的问题并在这些博客中找到了解决方案:
http://www.expertaya.com/2011/04/20/dbunit-composite-primary-keys/ http://blog.eflow.org/archives/65 http://www.baselogic.com/blog/development/test-driven-development/dbunit-unable-import-data-collectiontable-witout-primary-key/所有博客作者均以http://dbunit.wikidot.com/noprimarykeytable开头
这段代码展示了检查 id 的不同策略:
public static IDatabaseConnection getConnection(DataSource ds) throws Exception
Connection con = ds.getConnection();
final DatabaseMetaData dbMetaData = con.getMetaData();
DatabaseConnection dbUnitCon = new DatabaseConnection(con, dbMetaData.getUserName().toUpperCase());
DatabaseConfig dbUnitConfig = dbUnitCon.getConfig();
dbUnitConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new Oracle10DataTypeFactory());
dbUnitConfig.setProperty(DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES, Boolean.TRUE);
dbUnitConfig.setProperty(DatabaseConfig.PROPERTY_PRIMARY_KEY_FILTER, new IColumnFilter()
Map<String, List<String>> tablePrimaryKeyMap = new HashMap<>();
tablePrimaryKeyMap.put("CLIENT", Arrays.asList(new String[]"FIRST_NAME", "MIDDLE_NAME", "LAST_NAME"));
// ...
@Override
public boolean accept(String tableName, Column column)
if ((tableName.startsWith("DATA_") || tableName.startsWith("PAYMENT_"))
&& ("COMPANY".equalsIgnoreCase(tableName) || "FILIAL".equalsIgnoreCase(tableName)
|| "BRANCH".equalsIgnoreCase(tableName) || "CASTOMER".equalsIgnoreCase(tableName)
|| "XDATE".equalsIgnoreCase(tableName)))
return true;
if (tablePrimaryKeyMap.containsKey(tableName))
return tablePrimaryKeyMap.get(tableName).contains(column.getColumnName());
else if ("id".equalsIgnoreCase(column.getColumnName()))
return true;
try
ResultSet rs = dbMetaData.getPrimaryKeys(null, null, tableName);
while (rs.next())
rs.getString("COLUMN_NAME");
if (rs.getString("COLUMN_NAME").equalsIgnoreCase(column.getColumnName()))
return true;
catch (SQLException ex)
Logger.getLogger(DistributionControllerDbTest.class.getName()).log(Level.SEVERE, null, ex);
return false;
);
return dbUnitCon;
【讨论】:
以上是关于将 DbUnit 与没有主键的表一起使用的主要内容,如果未能解决你的问题,请参考以下文章