我需要向Octave实例提供从Oracle数据库检索到的数据。
我已经在我的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对象中的数据放入数组或矩阵中?
发布于 2019-04-20 21:31:32
找出该做什么
您想要用于ResultSet和相关类的文档在Java JDBC API documentation中。(您不需要特定于Oracle的文档,除非您想要做一些特定于Oracle的东西。所有JDBC驱动程序都符合通用JDBC API。)请看一下该教程和任何JDBC教程;因为它是一个Java对象,所以在Octave中使用的方法调用与在Java代码中使用的方法调用是相同的。
对于转换为倍频程的值,要知道Java原语会自动转换为倍频程类型,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_TYPE、CHAR_TYPE等的值应该是什么?您必须检查java.sql.Types Java类中的值。在运行时执行此操作,以确保与正在运行的JDK保持一致。
(注意:这段代码是一种简单、草率的方式。您可以(也应该)对其进行各种改进和优化。)
如何快速前进
不幸的是,这样做的性能会很糟糕,因为从Octave调用Java方法的开销很大,而且单元格保存数据的效率也很低。如果您的结果集很大,为了获得良好的性能,您需要用Java编写一个结果集缓冲层,它在Java中运行循环,并在每个列的原始数组中缓冲结果,并使用该缓冲层。如果你想要一个如何做到这一点的例子,我有an example implementation in Matlab in my Janklab library (M-代码层here)。请随意窃取代码。Octave不支持Java构造函数或类方法的点引用,因此要将其转换为Octave,需要将所有这些都替换为javaObject和javaMethod调用。(这很乏味,而且会导致丑陋的代码,所以我不打算自己去做。对不起。)
如果您不愿意这样做(说真的,谁愿意呢?),并且仍然需要良好的性能,那么您实际上应该做的是忘记将Octave直接连接到Oracle,而是编写一个单独的Python/NumPy或R程序,该程序接受您的查询,在Oracle数据库上运行它,并将结果写入一个.mat文件,然后您将从Octave读取该文件。
发布于 2019-04-02 20:22:53
我无法访问指定的.jar或合适的数据库来测试您的特定代码,但无论如何,这都不是一个八度的问题。实际上,您需要用于ResultSet类的相关api,以及处理它的标准方法。oracle documentation建议您在java中执行以下操作:
while (rs.next()) { System.out.println (rs.getString(1)); }因此,除了通过octave的java接口之外,这大概也是您在octave中要做的事情。一种可能的方式是
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数组转换成一个octave cell-object,或者反之亦然,据我所知这是不可能的。您必须通过for循环将元素从一个设置/获取到另一个,就像在java中所做的那样(例如,请参阅手册中关于javaArray函数的说明)。
https://stackoverflow.com/questions/55451683
复制相似问题