Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java CachedRowSetImpl getString基于列标签抛出;无效的列名";_Java_Sql_Jdbc_Resultset - Fatal编程技术网

Java CachedRowSetImpl getString基于列标签抛出;无效的列名";

Java CachedRowSetImpl getString基于列标签抛出;无效的列名";,java,sql,jdbc,resultset,Java,Sql,Jdbc,Resultset,当我执行以下代码时,一切正常: ResultSet rs = con.prepareStatement("SELECT r.UID AS R FROM r").executeQuery(); System.out.println(rs.getMetaData().getColumnLabel(1)); rs.next(); System.out.println(rs.getString("R")); 结果是: R 23 但当我执行以下代码时: ResultSet rs = con.prepa

当我执行以下代码时,一切正常:

ResultSet rs = con.prepareStatement("SELECT r.UID AS R FROM r").executeQuery();
System.out.println(rs.getMetaData().getColumnLabel(1));
rs.next();
System.out.println(rs.getString("R"));
结果是:

R
23
但当我执行以下代码时:

ResultSet rs = con.prepareStatement("SELECT r.UID AS R FROM r").executeQuery();
CachedRowSetImpl rslt = new CachedRowSetImpl();
rslt.populate(rs);
System.out.println(rslt.getMetaData().getColumnLabel(1));
rslt.next();
System.out.println(rslt.getString("R"));
结果是:

R
java.sql.SQLException:列名无效

为什么它会在这里抛出异常?

问题是
CachedRowSet
com.sun.rowset.CachedRowSetImpl
)的参考实现包含一个错误:当您按名称检索列时,它使用
columnName
,而不使用
columnLabel
,因此,与JDBC规范的其余部分相反,JDBC规范使用
columnLabel
来检索值。此错误使得无法通过
columnLabel
从行集中检索值

甲骨文的错误是,但是(令人惊讶,令人惊讶)他们已经使它无法供公众观看

有两种可能的解决办法。一个是检查驱动程序是否提供了一个属性来同时让
ResultSetMetaData.getColumnName(..)
方法返回
columnLabel
值,第二个解决方法是创建
CachedRowSetImpl
的子类(不幸的是,这需要大量重写方法)

以下版本是从此邮件复制的:

import java.math.BigDecimal;
导入java.sql.Array;
导入java.sql.Blob;
导入java.sql.Clob;
导入java.sql.Ref;
导入java.sql.SQLException;
导入java.util.Calendar;
导入java.util.Collection;
导入java.util.Hashtable;
导入javax.sql.rowset.RowSetMetaDataImpl;
导入com.sun.rowset.CachedRowSetImpl;
公共类FixedCachedRowSetImpl扩展了CachedRowSetImpl{
私有静态最终长serialVersionUID=-9067504047398250113L;
私有RowSetMetaDataImpl RowSetMD;
public FixedCachedRowSetImpl()引发SQLException{
超级();
}
public FixedCachedRowSetImpl(哈希表环境)引发SQLException{
高级工程师(环境);
}
private int getColIdxByName(字符串名)引发SQLException{
RowSetMD=(RowSetMetaDataImpl)this.getMetaData();
int cols=RowSetMD.getColumnCount();

对于(inti=1;i这里是我的改进版getColIdxByName,以支持MySQL 5.x名称,如“tbl.column”:

private int getColIdxByName(字符串名)引发SQLException{
RowSetMD=(RowSetMetaDataImpl)this.getMetaData();
int cols=RowSetMD.getColumnCount();

对于(inti=1;i最新的JDK1.7已经实现了CachedRowSet,标签名bug已经修复

import java.sql.ResultSet;
import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.RowSetFactory;
import javax.sql.rowset.RowSetProvider;

ResultSet rs = con.prepareStatement("SELECT r.UID AS R FROM r").executeQuery();
RowSetFactory rowSetFactory = RowSetProvider.newFactory();
CachedRowSet crs = rowSetFactory.createCachedRowSet();
crs.populate(rs);

您可以使用内部选择:

ResultSet rs = con.prepareStatement("SELECT * FROM (SELECT r.UID AS R FROM r) AA").executeQuery();
CachedRowSetImpl rslt = new CachedRowSetImpl();
rslt.populate(rs);
System.out.println(rslt.getMetaData().getColumnLabel(1));
rslt.next();
System.out.println(rslt.getString("R"));

一种解决方法似乎是将列包装在函数或数学运算中。然后可以在
CachedRowSetImpl
中使用别名

如果您的SQL是这样的:

SELECT
  id AS student_id,
  cost - discount AS total_cost,
  first_name AS name
FROM
  students
您可以引用
studentRow.getBigDecimal(“总成本”)
,但
studentRow.getLong(“学生id”)
studentRow.getString(“名称”)
将失败,并出现
SQLException
“无效列名”

但是如果您的SQL是这样的:

SELECT
  id + 0 AS student_id,
  cost - discount AS total_cost,
  CONCAT(first_name) AS name
FROM
  students
然后它会像你所期望的那样工作


我不确定这会对性能造成什么样的损失,但它会在紧要关头起作用。

在Netbeans中,我得到InvalidResultSetAccessException,在尝试创建新的ResultSetRappingSqlRowset(crs)时无法转换为throwable,其中crs是一个CachedRowSetIml。throws子句和try-catch都失败了。您能提出一些建议吗?对于第一个变体,您如何进行crs.populate(rs);如果没有看到填充方法,尽管它是从CachedRowSetImpl扩展而来的?@Zon
ResultSetRappingSqlRowset
可以-据我所知-只包装一个普通的
ResultSet
。你应该使用它而不是
CachedRowSetImpl
,而不是包装一个
CachedRowSetImpl
(这也会破坏包装的目的,因为已经太晚了).至于您的第二个问题:该方法存在于超类中,因此您应该能够调用它。在Java 7上不起作用-仍然是列名,没有列标签。这只是给了我一个错误
Table'.AA'。我的
PreparedStatement
ResultSet
工作正常。
SELECT
  id AS student_id,
  cost - discount AS total_cost,
  first_name AS name
FROM
  students
SELECT
  id + 0 AS student_id,
  cost - discount AS total_cost,
  CONCAT(first_name) AS name
FROM
  students