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()
的值不包含任何 Column
与 Column.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 代码中的任何地方,其中包含
@Column
和 MYFIELD
。请记住,注释可以跨越文件中的多行。
- 任何 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 的例子
我在 运行 我的测试中遇到以下错误:
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()
的值不包含任何 Column
与 Column.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 代码中的任何地方,其中包含
@Column
和MYFIELD
。请记住,注释可以跨越文件中的多行。 - 任何 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 的例子