在Java中执行R命令以从PostgreSQL访问数据并进行计算时出错

时间:2014-07-09 23:26:40

标签: java r postgresql rserve rpostgresql

我正在编写Java代码,我试图从PostgreSQL获取数据并对其进行简单计算(计算中位数)。首先,我从Java代码本身加载RPostgreSQL库,然后通过Java加载驱动程序并在R和PostgreSQL之间建立连接。但是,当我尝试通过Java触发查询命令(用于从PostgreSQL到R获取查询)时,我收到错误:

注意:此错误已解决。请在下面查看当前错误(脚本文件错误)

org.rosuda.REngine.REngineException: eval failed, request status: R parser: syntax error
org.rosuda.REngine.Rserve.RConnection.parseAndEval(RConnection.java:454)
org.rosuda.REngine.REngine.parseAndEval(REngine.java:108)
Rtemp.main(Rtemp.java:40)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:483)
com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

我目前的代码是:

import org.rosuda.REngine.REXP;
import org.rosuda.REngine.Rserve.*;

public class Rtemp {
  public static void main(String[] args) throws Exception {
    RConnection c = null;

    try {
      c = new RConnection();

      //Loading RPostgreSQL library
      REXP x = c.eval("library(RPostgreSQL)");

      //Loading PostgreSQL driver
      REXP drv = c.eval("dbDriver(\"PostgreSQL\")");

      // Establishing connection
      REXP r = c.parseAndEval("try(\"dbConnect(drv, host='localhost', port='5432',dbname='r1', user='postgres', password='pwd')\",silent=TRUE)");
      if (r.inherits("try-error")) System.err.println("Error: "+r.asString());
      else System.out.println("Success eval 1");


      REXP rs = c.parseAndEval("try(dbSendQuery(r,\"select colmn1 from host_brnd345633456_table1 limit 10 \"), silent=TRUE)");
      if (rs.inherits("try-error")) System.err.println("Error: "+rs.asString());
      else System.out.println("Success eval 2");



      REXP ftch = c.parseAndEval("try(ftch(rs,n=-1),silent=TRUE)");
      if (ftch.inherits("try-error")) System.err.println("Error: "+ftch.asString());
      else System.out.println("Success eval 3");

      REXP res = c.parseAndEval("try(median(ftch$colmn1),silent=TRUE)");
      if (res.inherits("try-error")) System.err.println("Error: "+res.asString());
      else {
        System.out.println("Success eval 4");
        System.out.println(res.asDouble());
      }
#The line 58 error mentioned below in the error section is coming at this line
      System.out.println(res.asDouble());
      //System.out.println(x.asString());
      System.out.println("Library loaded successfully");
    } catch(Exception e) {
      e.printStackTrace();
    } finally {
      if ( c != null )
        try {
          c.close();
        }
    }
  }
}

我不认为Rserve连接存在任何问题,因为显示R版本的简单代码正在被正确执行。

对于R到PostgreSQL部分编写命令的语法也没有问题,比如dbSendQuery()或者类似的,就像我在R中直接使用它们时它们工作得非常好。所以,我认为在Java中编写相同的问题(Java的相应语法)。

更新1:错误2(此错误已解决)

在接受@ on_the_shores_of_linux_sea的建议后,我修改了我的代码,但现在又出现了一个不同的错误:

    Success eval 1
Error: Error in is(object, Cl) : 
  error in evaluating the argument 'conn' in selecting a method for function 'dbSendQuery': Error: object 'r' not found


Error: Error in is(object, Cl) : 
  error in evaluating the argument 'res' in selecting a method for function 'fetch': Error: object 'rs' not found


Error: Error in median(ftch$t31001400) : object 'ftch' not found

org.rosuda.REngine.REXPMismatchException: attempt to access org.rosuda.REngine.REXPString as double
    at org.rosuda.REngine.REXP.asDoubles(REXP.java:77)
    at org.rosuda.REngine.REXP.asDouble(REXP.java:103)
    at Rtemp.main(Rtemp.java:58)
    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:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

Process finished with exit code 0

我无法弄清楚错误的原因以及解决方法

第二个问题:这是一个次要问题,因为我也想知道我可以在文件中写入R查询或语句(特殊的R格式文件或任何其他格式文件) )然后让Java读取文件并将R命令推入R以便执行它们?

更新2:脚本文件错误

下面@on_the_shores_of_linux_sea提到的方法1现在运行正常。我也试图通过方法2,但在通过Java管理脚本方面遇到一些困难。我正在使用的Java代码是:

public class Java_RScript {

    public static void main(String[] args) throws Exception {
        RConnection c = null;
        try {
            c = new RConnection();
            c.parseAndEval("try(source("script.R"),silent=TRUE)");
            REXP res = c.parseAndEval("try(\"do_operation()\", silent=TRUE)");
            System.out.println("Success:" + res.asDouble());
        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            if (c != null) {

                try {

                    c.close();

                } finally {
                }

            }

        }

    }
}

要打印的输出控制台上的错误如下:

org.rosuda.REngine.REXPMismatchException: attempt to access org.rosuda.REngine.REXPString as double

我的脚本文件语法是:

do_operation <- function()
 {
 drv <- dbDriver("PostgreSQL")
   r <- dbConnect(drv, host='localhost', port='1234',dbname='db', user='user1', password='pswd')
   rs <-dbSendQuery(r,"select colmn1 from hostess_table limit 10")
   ftch <- fetch(rs,n=-1)
   res <- median(ftch$colmn1)
   return(res)
 }

我不确定错误是在脚本文件还是我的Java语法中。

1 个答案:

答案 0 :(得分:1)

RENGINE如何工作,它通过套接字连接到Rserve会话,并通过eval或parseAndEval发送命令。 R session不知道在Java中创建的任何变量,所以如果你后续的evals中的那些变量,它将抛出错误

有两种方法可以解决您的问题

方法1 - 在evals中分配变量

import org.rosuda.REngine.REXP;
import org.rosuda.REngine.Rserve.*;

public class Rtemp {
public static void main(String[] args) throws Exception {
RConnection c = null;

try {
  c = new RConnection();

  //Loading RPostgreSQL library
  c.eval("library(RPostgreSQL)");
  //Loading PostgreSQL driver
  c.eval("drv <- dbDriver(\"PostgreSQL\")");

  // Establishing connection
  REXP r = c.parseAndEval("r <- try(\"dbConnect(drv, host='localhost', port='5432',dbname='r1', user='postgres', password='pwd')\",silent=TRUE)");
  if (r.inherits("try-error")) System.err.println("Error: "+r.asString());
  else System.out.println("Success eval 1");


  REXP rs = c.parseAndEval("try(rs <-dbSendQuery(r,\"select colmn1 from host_brnd345633456_table1 limit 10 \"), silent=TRUE)");
  if (rs.inherits("try-error")) System.err.println("Error: "+rs.asString());
  else System.out.println("Success eval 2");



  REXP ftch = c.parseAndEval("try(ftch <- ftch(rs,n=-1),silent=TRUE)");
  if (ftch.inherits("try-error")) System.err.println("Error: "+ftch.asString());
  else System.out.println("Success eval 3");

  REXP res = c.parseAndEval("try(res <- median(ftch$colmn1),silent=TRUE)");
  if (res.inherits("try-error")) System.err.println("Error: "+res.asString());
  else {
    System.out.println("Success eval 4");
    System.out.println(res.asDouble());
  }
  #The line 58 error mentioned below in the error section is coming at this line
  System.out.println(res.asDouble());
  //System.out.println(x.asString());
  System.out.println("Library loaded successfully");
} catch(Exception e) {
  e.printStackTrace();
} finally {
  if ( c != null )
    try {
      c.close();
    }
}

} }

方法2 - 使用R脚本并从代码

中获取文件

file script.R:

 require(PostgresSQL)
 do_operation <- function()
 {
   r <- dbConnect(drv, host='localhost', port='5432',dbname='r1', user='postgres', password='pwd')\",silent=TRUE)
   rs <-dbSendQuery(r,\"select colmn1 from host_brnd345633456_table1 limit 10
   ftch <- ftch(rs,n=-1)
   res <- median(ftch$colmn1)
   return(res)
 }

Java代码

  c = new RConnection();
  c.eval("source('script.R')");
  double res = c.eval("do_operation()").asDouble();