2012-02-03 27 views
6

我试图设置我的单元测试环境以使用DbUnit。对没有主键的表使用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"));

非常感谢您的任何建议。

回答

5

您需要确保MyPrimaryKeyFilter处理架构中的所有表。在这个例子中,只有一个表,所以简单的过滤器类提供的工作正常。在你的情况,我可能会改变这一类采取了在表中的地图 - > 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}条目。

+0

谢谢slushi。这就说得通了。如果其中一个表有一个由多个字段组成的密钥呢? – mip 2012-02-06 13:40:33

+1

我认为你可以将地图改成地图<字符串,设置>并做一个包含检查。 – slushi 2012-02-06 21:53:57

+0

所以return语句变成'return pseudoKey.get(tableName).contains(column.getColumnName());'? – mip 2012-02-07 09:18:21

3

我陷入同样的​​问题,找到解决方案,这些博客:

所有博客的作者开始从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; 
}