Octave:如何从Java ResultSet对象中检索数据?

问题描述 投票:1回答:2

我需要使用从Oracle数据库检索的数据来提供Octave实例。

我在Octave实例中实现了OJDBC连接,现在我可以将Oracle数据库中的数据放入Octave中的Java ResultSet对象中(取自:https://lists.gnu.org/archive/html/help-octave/2011-08/msg00250.html):

javaaddpath('access-path-to-ojdbc8.jar') ;
props = javaObject('java.util.Properties') ;
props.setProperty("user", 'username') ;
props.setProperty("password", 'password') ;
driver = javaObject('oracle.jdbc.OracleDriver') ;
url = 'jdbc:oracle:thin:@ip:port:schema' ;
con = driver.connect(url, props) ;
sql = 'select-query' ;
ps = con.prepareStatement(sql) ;
rs = ps.executeQuery() ;

但是没有成功从ResultSet中检索数据。

如何将Octave中ResultSet对象的数据放入数组或矩阵?

octave resultset ojdbc
2个回答
0
投票

我无权访问指定的.jar或合适的数据库来测试您的特定代码,但无论如何,这实际上并不是八度音阶的问题。实际上,您需要ResultSet类的相关API,以及处理它的标准方法。 oracle documentation建议在java中你做这样的事情:

while (rs.next()) { System.out.println (rs.getString(1)); }

因此,大概这也是你在octave中所做的,除了通过octave的java界面。这可能是一种可能的方式

while rs.next().booleanValue  % since a Boolean java object by itself
                              % isn't valid logical input for octave's
                              % 'while' statement
    % do something with rs, e.g. fill in a cell array
endwhile

至于你是否可以自动将java数组转换为八度单元格对象,反之亦然,据我所知这是不可能的。你必须通过for循环设置/获取元素从一个到另一个,就像你在java中一样(例如,参见手册中有关javaArray函数的注释)


0
投票

找出该做什么

你想要的ResultSet和相关课程的文档都在Java JDBC API documentation中。 (除非你想做特定于Oracle的特定事情,否则你不需要特定于Oracle的doco。所有JDBC驱动程序都符合通用JDBC API。)看看它和任何JDBC教程;因为它是一个Java对象,所以你将使用Octave中与Java代码相同的所有方法调用。

要转换为Octave值,请知道Java基元自动转换为Octave类型,java.lang.String对象需要通过调用char(...)进行转换,而java.sql.Date值则必须手动转换为datenums。 (懒惰的方法是获取它们的字符串值并解析它们;快速的方法是获取它们的Unix时间值并进行数字转换。)

该怎么办

因为Java JDBC一次将结果集游标提前一行,并且需要单独的方法调用来获取每列的值,所以需要使用一对嵌套循环来迭代ResultSet。像这样:

rsMeta = rs.getMetaData();
nCols = rsMeta.getColumnCount();
data = NaN(1, nCols);
iRow = 0;
while rs.next()
  iRow = iRow + 1;
  for iCol = 1:nCols
    data(iRow,iCol) = rs.getDouble(iCol);
  endfor
endwhile

啊,但如果你的专栏不是全部数字怎么办?然后,您需要查看rsMeta中的列类型,打开它,并使用单元格数组来保存异构数据集。像这样:

rsMeta = rs.getMetaData();
nCols = rsMeta.getColumnCount();
data = cell(1, nCols);
iRow = 0;
while rs.next()
  iRow = iRow + 1;
  for iCol = 1:nCols
    colTypeId = rsMeta.getColumnType(iCol);
    switch colTypeId
      case NUMERIC_TYPE
        data{iRow,iCol} = rs.getDouble(iCol);
      case CHAR_TYPE
        data{iRow,iCol} = rs.getString(iCol);
        data{iRow,iCol} = char(data{iRow,iCol});
      # ... and so on ...
      otherwise
        error('Unsupported SQL data type in column %d: %d', ...
          iCol, colTypeId);
    endswitch
  endfor
endwhile

你怎么知道NUMERIC_TYPECHAR_TYPE等的值应该是多少?您必须检查java.sql.Types Java类中的值。在运行时执行此操作以确保您与正在运行的JDK保持一致。

(注意:这段代码是简单,草率的方式。你可以(而且应该)对它进行各种改进和优化。)

怎么走得快

不幸的是,由于Octave的Java方法调用很昂贵,并且单元格保持数据的效率低下,因此性能的下降会占用大量时间。如果结果集很大,为了获得良好的性能,您需要做的是在Java中编写一个结果集缓冲层,在Java中运行循环并将结果缓存在原始的每列数组中,然后使用它。如果你想要一个如何做到这一点的例子,我有an example implementation in Matlab in my Janklab library(M代码层here)。随意窃取代码。 Octave不支持Java构造函数或类方法的点引用,因此要将其转换为Octave,您需要使用javaObjectjavaMethod调用替换所有这些。 (这很乏味,导致代码难看,所以我自己也不会这样做。抱歉。)

如果你不愿意这样做(真的,谁是?),并且仍然需要良好的性能,你应该忘记将Octave直接连接到Oracle,并编写一个单独的Python / NumPy或R程序您的查询,针对您的Oracle数据库运行它,并将结果写入.mat文件,然后您将从Octave中读取该文件。

© www.soinside.com 2019 - 2024. All rights reserved.