【问题标题】:Oracle JDBC transaction management and committing sessionsOracle JDBC 事务管理和提交会话
【发布时间】:2011-07-12 18:34:41
【问题描述】:

假设我有以下代码

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;


    public class TestClass {

        public static void main(String args[]) throws ClassNotFoundException, SQLException{

            Connection database; 

            Class.forName("oracle.jdbc.driver.OracleDriver");
            database = 
                DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:mydb", "user", "pass");

            if (database.getAutoCommit())
                database.setAutoCommit(false);

            String insertParent = "Insert into ParentTable (parentId,name,value) values(parentSeq.nextval,?,?)";
            String insertChild = "Insert into ChildTable (childId,parentId,value) values(childSeq.nextval,?,?)";


            PreparedStatement addParentStmt = null;
            PreparedStatement addChildStmt  = null;

            //Add the parent record
            addParentStmt = database.prepareStatement(insertParent);

            addParentStmt.setString(1,"Fruit"); 
            addParentStmt.setString(2,"Orange");

            addParentStmt.executeUpdate();

            //Now retrieve the id of the parent row to insert into the child row

            Statement stmt  = null;
            ResultSet rs    = null;

            stmt = database.createStatement();
            rs = stmt.executeQuery("Select parentId from parentTable where value='Orange'");

            //Now insert into the child table

            addChildStmt = database.prepareStatement(insertChild );

            if(rs.next()){
                addChildStmt.setInt(1,rs.getInt("parentId"));
            }

            addChildStmt.setString(2,"The Orange child");

            addChildStmt.executeUpdate(insertChild);

            addChildStmt.close();
            addParentStmt.close();

            database.commit();

        }

    }

现在每次我运行上面我都会收到以下错误。

java.sql.SQLException: ORA-01008: not all variables bound

当我调试它时,异常出现在 addChildStmt.executeUpdate(insertChild); 行处

我不想在插入父记录后发出提交。我的理解是,如果我在同一个会话中,我不必承诺。上面显示的第二个插入语句是否与第一个不在同一会话中?为什么即使我刚刚插入记录,rs.next() 也不返回任何值?

谢谢

编辑

要编译上述代码,oracle 中需要以下表格

create table ParentTable(parentId number, name varchar(20), value varchar(20));
create table childTable(childI number, parentid number, value varchar(20));

Oracle 中还需要两个序列 parentSeq 和 childSeq。

谢谢

【问题讨论】:

  • 请贴出真实代码。您发布的代码无法编译
  • 嗨,该代码只是我想要实现的一个示例。
  • 因为它不是真正的代码,所以很难判断异常来自哪里。例如,您的 insertChild 查询要插入三列,并插入 4 个值。您在 addTransactionRecord 上执行更新,甚至没有声明。所有这些都可能是您真实代码中的错误,但由于我们没有,我们无法判断。
  • 抱歉,我已修正错别字。异常发生在 addChildStmt.executeUpdate(insertChild) 期间。原因是 if(rs.next()) 永远不会返回 true。我要问的是为什么我不能从同一会话中读取我没有提交的行。谢谢

标签: java oracle jdbc oracle10g session-state


【解决方案1】:

由于这不是真正的代码,因此很难判断错误在哪里。但是策略本身是错误的:如果 Orange 不是唯一标识符,它就无法工作。你应该

  1. 执行select语句从父序列中获取下一个值,并得到一个父ID
  2. 执行插入语句以插入具有此父 ID 的父
  3. 执行select语句从子序列中获取下一个值,得到一个子ID
  4. 执行插入语句以插入具有父 ID 和子 ID 的子代。

已编辑:

现在代码没问题,我找到了错误。替换

addChildStmt.executeUpdate(insertChild);

addChildStmt.executeUpdate();

(并修复 childId 列的名称)。调试器或简单日志会显示选择查询确实返回父 ID。

【讨论】:

  • 嗨,这是我想要做的,但我通过读取父行来获取 id。假设 Orange 是独一无二的,我将如何读取我刚刚插入的行。我遇到的问题是我无法读取刚刚插入的行而无需先提交。
  • 您应该能够在不提交的情况下阅读刚刚插入的内容。您的代码中可能存在错误,但您不想显示它。
  • 您好,抱歉,不是我不想展示它。查询是动态生成的,因此几乎不可能在不发布多个源文件和包含查询字符串的某些表的内容的情况下显示它。这就是我试图展示上面例子的原因。因此,如果我发出一个插入语句,我应该能够读取我刚刚插入的记录而不提交?如果使用不同的 PreparedStatement 会有什么不同吗?
  • 如果不是同一个连接会有所不同。如果它不是真正的代码,这不是问题。但它应该是可以编译的代码,你尝试过运行,这就是问题所在。见sscce.org
  • 好的,我已经使用更新版本对其进行了编辑,该版本编译良好,但在 addChildStmt.executeUpdate(insertChild) 行失败。
猜你喜欢
  • 2021-04-18
  • 2013-03-10
  • 1970-01-01
  • 1970-01-01
  • 2019-12-09
  • 1970-01-01
  • 2015-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多