3

我有连接到远程 oracle 11g EE db 服务器的 java 代码。如果我在 sqlplus 中运行特定查询,它会返回一个结果

SQL> SELECT COURSENAME from COURSES where skillID=1;

COURSENAME
--------------------
basic

但是,如果我从下面的 java 代码运行相同的查询,它不会返回任何结果。我可以从 java 调试器中的变量中复制查询语法query并在 oracle 上运行它,所以我知道查询没有语法问题。此外,它不是 SQL 异常或类未找到异常,因此它似乎正在成功运行查询——只返回零结果。

可能会发生什么?

    private String getCourseForSkill(int skillID){
    try{
        Class.forName("oracle.jdbc.OracleDriver"); 
        String query="SELECT COURSENAME from COURSES where skillID=" + skillID ; 
        con = DriverManager.getConnection(url, user, password);
        Statement stmt = con.createStatement();
        rs = stmt.executeQuery(query);
        rs.next();
        return rs.getString("COURSENAME");
    }
    catch (ClassNotFoundException ex){
        System.out.println(ex.getMessage());
    }
    catch (SQLException ex) {
         System.out.println(ex.getMessage());
    }
    return null;
}
4

4 回答 4

5
  1. 我认为您正在连接到不同的 Oracle 实例,或者更有可能在这两种情况下作为不同的 Oracle 用户

    @GreyBeardedGeek URL 看起来像“jdbc:oracle:thin:@website:port:orcl 我通过执行 ssh@website、身份验证然后运行 ​​command=sqlplus 来手动查询

    运行更安全sqlplus <username>/<password>@<orainstancename>,因为您可以显式指定 oracle 实例 ID。在您的情况下,您的程序似乎正在使用 jdbc 连接jdbc:oracle:thin:@website:port:orcl,因此您的 orainstancename 将是“ orcl ” - 只需确保您的tnsnames.ora文件具有实例“ orcl ”,并且与jdbc 连接使用的“端口”相同

  2. 如何调试更多

    运行以下代码:

    con = DriverManager.getConnection(url, user, password);
    con.setAutoCommit(false);
    String insert="INSERT INTO COURSES (SKILLID, COURSE)"+ // can add other columns
                 "values (?, ?) );"                       // add ? for other columns    
    PreparedStatement ps = con.createPreparedStatement();
    ps.setInt(1, 999);
    ps.setString(2, "Complete Bullwarks");
    // can set other columns
    ps.executeUpdate(insert);
    con.commit();
    

    现在手动连接,重新运行原始选择语句并查看添加的行是否存在。如果 java 中没有错误并且 Oracle 中没有新行:您很可能正在使用 2 个不同的 Oracle 实例/模式。

    还重新运行您原来的 java 选择代码,但使用 SkillID=999 - 极有可能它会工作。

干杯

于 2013-04-19T04:25:22.833 回答
2

我必须提交才能添加行。当我输入commit;sql plus 终端时,远程 jdbc 连接可以“看到”这些行。我习惯使用 linq-to-sql 或 sql management studio 时不必显式执行此类提交的 SQL Server。

于 2013-04-23T14:59:09.283 回答
0

可以是三个问题。

1)skillID <> 1 在您的 Java 代码中。添加调试和检查。

2a) 您正在连接到另一个数据库。

2b)您正在连接到同一个数据库,但从另一个模式中的表中进行选择。

要检查 2a 和 2b:

从双重中选择用户;-- 连接用户名

从 v$database 中选择名称; - 数据库名称

从 v$instance 中选择主机名;-- 主机名数据库正在运行

此查询将所有三个返回到一个结果中。

选择用户 || ' ' || d.name || ' ' || i.host_name 来自 v$database d, v$instance i;

于 2013-04-23T21:42:19.780 回答
0

假设您实际上连接到同一个数据库,这是由于未INSERT在 sql*plus 连接中提交。

默认情况下,通过 OCI(sql*plus 用于连接)连接时,Oracle不会在自动提交模式下运行。在 sql*plus 中执行的任何DML ( INSERT ...) 在提交之前对任何其他会话都是不可见的。这是因为 Oracle 默认提供了已提交读隔离级别。跨会话的其他用户唯一可见的是写锁。

如果您通过 JDBC 或 OCI 连接第二个连接并不重要,在您提交第一个连接之前它不会看到更改。


要对此进行测试,请尝试打开 2 个 sql*plus 连接并运行以下命令:

-- Executing DDL in Oracle causes an implicit commit before and after the
-- command so the second connection will see the existence of this table:
CREATE TABLE foobar ( x VARCHAR(1) );

在连接 #1 中执行这个 - 你应该得到零(我们还没有插入任何东西):

SELECT COUNT(*) FROM foobar;

在连接 #2 中执行此操作:

INSERT INTO foobar ( x ) VALUES ( 'A' );

在连接 #1 中执行此操作 - 您仍然应该得到零(INSERT未提交,因此连接 #1 看不到它):

SELECT COUNT(*) FROM foobar;

在连接 #2 中执行此操作:

COMMIT;

在连接 #1 中执行此操作 - 你应该得到 1(它现在已提交):

SELECT COUNT(*) FROM foobar;
于 2013-04-24T08:21:20.043 回答