【问题标题】:Using DbUnit with tables which do not have primary keys将 DbUnit 与没有主键的表一起使用
【发布时间】: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"));

非常感谢您的建议。

【问题讨论】:

    标签: java junit dbunit


    【解决方案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 更改为 Map> 并进行包含检查。
    • 所以return语句变成return pseudoKey.get(tableName).contains(column.getColumnName());?
    • 我认为是这样,您可能需要稍微更改它以处理不区分大小写的问题。我会进行测试以查看 column.getColumnName() 返回的情况。或者您可以将 Set 中的所有内容以及 column.getColumnName() 中的值大写。
    【解决方案2】:

    我遇到了同样的问题并在这些博客中找到了解决方案:

    所有博客作者均以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;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-07-07
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-20
      • 1970-01-01
      • 2023-01-26
      • 1970-01-01
      相关资源
      最近更新 更多