org.dbunit.dataset.NoSuchColumnException

org.dbunit.dataset.NoSuchColumnException

我在 运行 我的测试中遇到以下错误:

org.dbunit.dataset.NoSuchColumnException: myTable.MYFIELD -  (Non-uppercase input column: myfield) in ColumnNameToIndexes cache map. Note that the map's column names are NOT case sensitive.
    at org.dbunit.dataset.AbstractTableMetaData.getColumnIndex(AbstractTableMetaData.java:117)

我在org.dbunit.dataset.AbstractTableMetaData#getColumnIndex中设置了一个断点并发现了以下内容。在 IntelliJ Idea 中,方法如下所示:

public int getColumnIndex(String columnName) throws DataSetException 
{
    logger.debug("getColumnIndex(columnName={}) - start", columnName);

    if(this._columnsToIndexes == null) 
    {
        // lazily create the map
        this._columnsToIndexes = createColumnIndexesMap(this.getColumns());
    }

    String columnNameUpperCase = columnName.toUpperCase();
    Integer colIndex = (Integer) this._columnsToIndexes.get(columnNameUpperCase);
    if(colIndex != null) 
    {
        return colIndex.intValue();
    }
    else 
    {
        throw new NoSuchColumnException(this.getTableName(), columnNameUpperCase,
                " (Non-uppercase input column: "+columnName+") in ColumnNameToIndexes cache map. " +
                "Note that the map's column names are NOT case sensitive.");
    }
}

this.getColumns() 的值不包含任何 ColumnColumn.columnName 匹配参数 columnName。因此 colIndex 变为 null 并抛出异常。

看起来 DBUnit 在错误的 table 元数据中寻找列索引。

我该如何解决这个问题?

注:这段代码是我从别人那里继承过来的(不是自己写的)

我对您不能真正共享代码这一事实很敏感。这确实让事情变得有点困难,但考虑到限制,我认为这是一个合理的答案:

我能够使用 minimal Spring Boot/DbUnit project cloned from GitHub 轻松重现此异常。或许我的观察会成为您正在寻找的提示,或者至少会激发出更好的答案。

步骤

  • 克隆 the project 并安装依赖项。
  • 运行 HsqldbexampleApplicationTests.contextLoads() 测试。它通过了。
  • 进入 StaticResource.java,并更改其中一个 @Column 注释。

比如我改成:

@Column(name = "CONTENT")
private String content;

至:

@Column(name = "CONTENTZ")
private String content;
  • 运行再次测试,观察异常
  • 或者,您可以进入 sampleData.xml 并在那里更改 CONTENT 属性(属性 name),以产生相同的异常。

观察结果

  • 测试从 /META-INF/dbtest/sampleData.xml 获取数据。注意 CONTENT 属性。
  • 该资源有一个 @Column 注释,其 name 必须与在 sampleData.xml 元素中找到的属性相匹配。
  • 由于您的问题也与 运行 测试有关,可能是您的代码和补充测试数据存储的 .xml(?) 与列不同步名字.

XML 文件的进一步含义?

我尝试通过更改查询和实例变量名称来引发此异常,但没有成功。我尝试的一切都让编译器抱怨,所以我排除了它。

例如,我也查看了this repo,并尝试更改查询和实例变量,但每一步都被编译器阻止。更改查询:

更改实例变量名称:

在哪里看

  • 在任何 java 代码中的任何地方,其中包含 @ColumnMYFIELD。请记住,注释可以跨越文件中的多行。
  • 任何 xml 个包含 MYFIELD.
  • 的文件
  • 假设被测代码工作正常,并且您的问题仅限于 运行 测试,将数据注入测试的机制是主要嫌疑人。如果这个不是一个xml文件,它是什么?

你不清楚post你是怎么得到的_columnsToIndexes 它看起来像是一段依赖于您的 POJO 的反射代码。 在这种情况下,问题可能出在对象的 Lazy 初始化中。延迟初始化的对象不仅仅是实体对象,而且某种代理和通过反射获取其属性的尝试可能会导致此问题。 或许你应该尝试添加某种非代理方法到你 createColumnIndexesMap。这是示例:

public static <T> T initializeAndUnproxy(T entity) {
    if (entity == null) {
      throw new InternalServerException("Entity passed for initialization is null");
    }

    T unproxy = entity;
    Hibernate.initialize(entity);
    if (isProxy(entity)) {
      unproxy = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
    }
    return unproxy;
  }
  public static <T> boolean isProxy(T entity) {
    return entity instanceof HibernateProxy;
  }

当然这取决于你的 ORM,这里是 Hibernate 的例子