在 ColdFusion 中生成 QueryTable 成功,但在 Java 中失败

Generating a QueryTable succeeds in ColdFusion but fails in Java

我有 Java 代码片段:

import coldfusion.runtime.Struct;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.OracleCallableStatement;

public class CursorTest {
  public static Struct getCursor() throws SQLException {
    OracleCallableStatement statement = null;
    Struct variables = new Struct();
    // prepare statement with a cursor out parameter
    ResultSet results = statement.getCursor( 1 );
    variables.put ( "cursor", results );
    return variables;
  }
}

在构建路径中包括来自 ColdFusion lib 目录和 Oracle ojdbc6.jarcfusion.jar 和修补程序 jar。

我可以 运行 在 ColdFusion 中:

<cfscript>
  vars   = createObject( 'java', 'CursorTest' ).getCursor();
  cursor = createObject( 'java', 'coldfusion.sql.QueryTable' )
             .init( vars.cursor )
             .firstTable();
  WriteDump( cursor );
  // close the statement and connection.
</cfscript>

这有效,QueryTable 已创建。

但是,尝试将 QueryTable 的生成移动到 Java 代码中:

import coldfusion.runtime.Struct;
import coldfusion.sql.QueryTable;
import coldfusion.sql.Table;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.OracleCallableStatement;

public class CursorTest {
  public static Struct getCursor() throws SQLException {
    OracleCallableStatement statement = null;
    Struct variables = new Struct();
    // prepare statement with a cursor out parameter
    ResultSet results = statement.getCursor( 1 );
    Table table = new QueryTable( results ).firstTable();
    variables.put ( "cursor", table );
    return variables;
  }
}

构建失败:

error: cannot access QueryTableWrapper
      Table table = new QueryTable( results ).firstTable();
                    ^
  class file for coldfusion.runtime.QueryTableWrapper not found

现在,错误是不言自明的,解压 Jar 文件显示该文件不存在......但是,我无法在 ColdFusion lib 目录(ColdFusion 的 JRE)中的任何其他 Jar 文件中找到它可能在 ColdFusion 的 class 路径上的目录或其他 Jars。

有谁知道这个文件的位置,以便我可以将它包含在构建路径中,或者,ColdFusion 如何在没有包装器的情况下使用 createObject 设法生成 QueryTable

coldFusion.sql.QueryTable 有多个构造函数:

  • QueryTable()
  • QueryTable( Query cfx )
  • QueryTable( QueryTable rs )
  • QueryTable( QueryTableWrapper qtWrapper )
  • QueryTable( ResultSet rs )
  • QueryTable( int rows )
  • QueryTable( QueryTable rs, int maxrows )
  • QueryTable( int rows, String collist )
  • QueryTable( int rows, String[] cols )
  • QueryTable( int rows, String[] cols, String[] sqlColTypeNames )
  • QueryTable( int rows, String[] cols, String[] sqlColTypeNames, int[] sqlColTypes )

那里列出的前 7 个构造函数都在表面之下的某个地方使用了 QueryTableWrapper,并且在 Java 中失败,因为找不到 class。

但是,QueryTable( int rows, String[] cols, String[] sqlColTypeNames, int[] sqlColTypes ) 不使用此包装器。

因此,虽然您不能传入 ResultSetQuery 或现有的 QueryTable 并让构造函数自动解析它,但您可以生成一个空的 QueryTable 然后解析 ResultSet 并将其逐行添加到 QueryTable 中,如下所示:

final OracleResultSet results    = statement.getCursor( 1 );
final ResultSetMetaData metadata = results.getMetadata();
final int columns                = metadata.getColumnCount();
final String[] colNames          = new String[ columns ];
final String[] sqlColTypeNames   = new String[ columns ];
final int[] sqlColTypes          = new int[ columns ];
final boolean[] caseSensitive    = new boolean[ columns ];

for ( int i = 1; i <= columns; i++ )
{
  colNames[i-1]        = metadata.getColumnName( i );
  sqlColTypeNames[i-1] = metadata.getColumnTypeName( i );
  sqlColTypes[i-1]     = metadata.getColumnType( i );
  caseSensitive[i-1]   = metadata.isCaseSensitive( i );
}
final QueryTable table = new QueryTable(
  0,
  colNames,
  sqlColTypeNames,
  sqlColTypes
);
table.getMeta().setColumnCase( caseSensitive );

int rows = 0;
while ( results.next() )
{
  table.addRows( 1 );
  ++rows;
  for ( int c = 1; c <= columns; ++c )
  {
    Object value = null;
    switch( sqlColTypes[c-1] )
    {
      case OracleTypes.ARRAY:   value = results.getARRAY( c ).getArray();
                                break;
      case OracleTypes.VARCHAR: value = results.getString( c );
                                break;
      case OracleTypes.DATE:    value = results.getDate( c );
                                break;
      case OracleTypes.NUMERIC: value = results.getBigDecimal( c );
                                break;
      // Add other types
      default:                throw new UnsupportedOperationException( "Unable to handle: " + sqlColTypes[c-1] );
    }
    if ( results.wasNull() )
    {
      value = null;
    }
    table.setField( rows, c, value );
  }
}

然后可以将 QueryTable.firstTable() 返回给 ColdFusion 并将其用作任何内置 ColdFusion 函数生成的查询结果。