org.dbunit.dataset.NoSuchColumnException

Posted

技术标签:

【中文标题】org.dbunit.dataset.NoSuchColumnException【英文标题】: 【发布时间】:2018-04-26 03:43:40 【问题描述】:

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

: 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 在错误的表元数据中寻找列索引。

我该如何解决这个问题?

注意:我从别人那里继承了这段代码(不是写的)。

【问题讨论】:

既然您已经对问题进行了详细分析,我想问这个问题的最佳地点是非 DBUnit 支持论坛。 有两个可能的原因。 DBUnit 是错误的。或者,您在某些注释中提供了错误的 columnName 或错误命名的 getter/setter 对。 您需要显示更多的代码,以便有人更好地了解情况。另外,在您的情况下使用了哪个表,您是否检查过它的来源? @TarunLalwani 我到底能找到什么? 这是一个 JPA 项目吗?测试数据库是如何创建的?另请参阅此处以启用所有正在生成的 SQL 的日志记录,包括表创建和 iserts ***.com/a/19299769/1356423 【参考方案1】:

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

我能够使用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,并尝试更改查询和实例变量,但在每一步都被编译器阻挠。更改查询:

更改实例变量名称:

去哪里看

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

【讨论】:

【参考方案2】:

您的帖子不清楚您如何获得_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 的例子

【讨论】:

以上是关于org.dbunit.dataset.NoSuchColumnException的主要内容,如果未能解决你的问题,请参考以下文章