java.sql.SQLException: 无效的列名

24

我无法弄清楚为什么这里出现了“无效的列名”

我们已经在Oracle中直接尝试了SQL的变体,它可以正常工作,但是当我使用jdbcTemplate时,发生了一些错误。

List<Dataholder> alleXmler = jdbcTemplate.query("select p.applicationid, x.datadocumentid, x.datadocumentxml " +
                        "from CFUSERENGINE51.PROCESSENGINE p " +
                        "left join CFUSERENGINE51.DATADOCUMENTXML x " +
                        "on p.processengineguid = x.processengineguid " +
                        "where x.datadocumentid = 'Disbursment' " +
                        "and p.phasecacheid = 'Disbursed' ",
                (rs, rowNum) -> {
                    return Dataholder.builder()
                            .applicationid(rs.getInt("p.applicationid"))
                            .datadocumentId(rs.getInt("x.datadocumentid"))
                            .xml(lobHandler.getClobAsString(rs, "x.datadocumentxml"))
                            .build();
                });

适用于Oracle的完整SQL如下:

select
process.applicationid,
xml.datadocumentid,
xml.datadocumentxml
from CFUSERENGINE51.PROCESSENGINE process
left join CFUSERENGINE51.DATADOCUMENTXML xml
on process.processengineguid = xml. processengineguid
where xml.datadocumentid = 'Disbursment'
and process.phasecacheid = 'Disbursed'
and process.lastupdatetime > sysdate-14

整个堆栈跟踪:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:507)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:803)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:784)
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:771)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1186)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1175)
    at no.gjensidige.bank.datavarehus.kontonrinfridd.Application.main(Application.java:44)
    ... 6 more
Caused by: org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [select p.applicationid, x.datadocumentid, x.datadocumentxml from CFUSERENGINE51.PROCESSENGINE p left join CFUSERENGINE51.DATADOCUMENTXML x on p.processengineguid = x.processengineguid where x.datadocumentid = 'Disbursment' ]; nested exception is java.sql.SQLException: Invalid column name
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:419)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:474)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:484)
    at no.gjensidige.bank.datavarehus.kontonrinfridd.Application.run(Application.java:61)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:800)
    ... 12 more
Caused by: java.sql.SQLException: Invalid column name
    at oracle.jdbc.driver.OracleStatement.getColumnIndex(OracleStatement.java:4146)
    at oracle.jdbc.driver.InsensitiveScrollableResultSet.findColumn(InsensitiveScrollableResultSet.java:300)
    at oracle.jdbc.driver.GeneratedResultSet.getString(GeneratedResultSet.java:1460)
    at org.apache.commons.dbcp2.DelegatingResultSet.getString(DelegatingResultSet.java:267)
    at org.apache.commons.dbcp2.DelegatingResultSet.getString(DelegatingResultSet.java:267)
    at no.gjensidige.bank.datavarehus.kontonrinfridd.Application.lambda$run$0(Application.java:69)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:93)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:60)
    at org.springframework.jdbc.core.JdbcTemplate$1QueryStatementCallback.doInStatement(JdbcTemplate.java:463)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:408)
    ... 16 more

你的表是如何定义的?在Oracle上直接尝试变量的效果如何?请将它们添加到你的问题中。 - Alfabravo
@Alfabravo,老实说我不知道。这个SQL是别人发给我的,他向我展示了它在Oracle中直接运行的情况。所以我知道它应该可以工作。但是“无效列名”意味着这不是来自Oracle的错误,而是spring-jdbc本身的错误。所以我认为应该是一些显而易见的问题,只是对我来说不太明显 :) - Shervin Asgari
那么你甚至没有无效列的名称?我们应该如何帮助你呢? - juergen d
请添加堆栈跟踪信息。仅说“无效的列名”没有任何意义。 - Kayaman
@Berger 那个空格不应该存在。我只是尝试加上空格,因为我得到的 SQL 语句中有空格。但我想这只是一个复制/粘贴错误。即使有或没有空格,我仍然会得到相同的错误。 - Shervin Asgari
显示剩余4条评论
3个回答

62

问题不在查询上。查询运行正常。

问题在于行映射,将ResultSet中的一行转换为领域对象。看起来在你的应用程序中,作为行映射的一部分,你正在尝试从ResultSet中读取一个它本身不包含的列的值。

在堆栈跟踪中,关键行是最后靠近底部的以下三行:

    at org.apache.commons.dbcp2.DelegatingResultSet.getString(DelegatingResultSet.java:267)
    at no.gjensidige.bank.datavarehus.kontonrinfridd.Application.lambda$run$0(Application.java:69)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:93)

在您的代码中,这三行中的中间一行似乎是有问题的。 您的Application类的第69行包含一个lambda表达式,该表达式调用ResultSet.getString(),但由于这导致出现“无效列名”错误,因此(a)您正在传递一个字符串作为列名而不是数字列索引,并且(b)您传递的列名在结果集中不存在。

现在,您已经编辑了问题以包括对jdbcTemplate.query()的调用,特别是负责将结果集行映射到对象的lambda表达式,问题变得更加清晰。 当使用列名称而不是索引调用rs.getInt(...)rs.getString(...)时,请勿包括诸如p.x.之类的前缀。 不要写成rs.getInt("p.applicationid")rs.getInt("x.datadocumentid"),而应该写成rs.getInt("applicationid")rs.getInt("datadocumentid")


我认为你在这方面有所发现。这是因为我不了解jdbcTemplate的工作原理。我已经更新了问题,并附上了我尝试读取数据的代码。你能看一下吗?我将getString()改为getInt(),但仍然无法正常工作。 - Shervin Asgari
我终于通过使用getObject(int index)让它工作了。谢谢。从错误信息中并不是很清楚。 - Shervin Asgari
1
@ShervinAsgari:在调用getIntgetString时,请从列名中删除前缀p.x.:它们应该是applicationiddatadocumentid,而不是p.applicationidx.datadocumentid - Luke Woodward
@ShervinAsgari。你有什么想法是什么问题,最终的解决方案是什么吗?我遇到了同样的错误,它在我的本地环境中可以工作,但在UAT中却不能。 - Stunner
@Stunner我改用索引而不是列名。 这个方法有效。为什么它在你的UAT环境中无法工作,我不知道。也许你应该调试所有参数并确保它们没有奇怪的值。 - Shervin Asgari
最终成功解决了这个问题。问题出在sortKey属性标签上。属性名称为“sortKey”,值为“columnName”/>。无论我们在此标记中给定哪个列名,都应该在选择查询中存在相同的列。如果缺少它,则会出现此无效列错误。 - Stunner

2

java.sql.SQLException: 无效的列名 在oracle.jdbc.driver.OracleStatement.getColumnIndex(OracleStatement.java:4146) 在oracle.jdbc.driver.InsensitiveScrollableResultSet.findColumn(InsensitiveScrollableResultSet.java:300) 在oracle.jdbc.driver.GeneratedResultSet.getInt(GeneratedResultSet.java:1350) 在com.zaxxer.hikari.pool.HikariProxyResultSet.getInt(HikariProxyResultSet.java)

当您尝试从Resultset中获取不存在的index_name时,也会出现此问题,请检查您的查询并与您正在尝试从ResultSet中获取的列索引名称进行匹配。这可能是造成此问题的原因之一。


0
你需要表格定义来找到问题所在。安装/运行Oracle SQL Developer(它是免费的),设置JDBC连接并调查架构。
你需要检查以下列是否存在:
CFUSERENGINE51.PROCESSENGINE.applicationid,
CFUSERENGINE51.PROCESSENGINE.lastupdatetime
CFUSERENGINE51.PROCESSENGINE.phasecacheid
CFUSERENGINE51.PROCESSENGINE.processengineguid
CFUSERENGINE51.DATADOCUMENTXML.datadocumentid
CFUSERENGINE51.DATADOCUMENTXML.datadocumentxml
CFUSERENGINE51.DATADOCUMENTXML.processengineguid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接