【问题标题】:CachedRowset acceptChanges not working after insert opertion插入操作后,CachedRowset acceptChanges 不起作用
【发布时间】:2014-10-31 13:15:26
【问题描述】:

我正在使用 MySQL 数据库,我有一个表 Employee 有 2 列:Id(整数;主键)和 Name(字符串)。我已经编写了一些代码来在Employee 表中插入一行,但是acceptChanges 不起作用并且代码在acceptChanges 处停止。代码如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.RowSetFactory;
import javax.sql.rowset.RowSetProvider;

public class InsertSynchronizer {

    static CachedRowSet crs = null;

    public static void main(String[] args) {

        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection c = DriverManager.getConnection("jdbc:mysql://localhost:3306/", "root", "");
            c.setAutoCommit(false);
            RowSetFactory myRowSetFactory = null;
            myRowSetFactory = RowSetProvider.newFactory();
            crs = myRowSetFactory.createCachedRowSet();
            crs.setUrl("jdbc:mysql://localhost:3306/test");
            crs.setUsername("root");
            crs.setPassword("");
            crs.setConcurrency(CachedRowSet.CONCUR_UPDATABLE);
            crs.setCommand("select * from employee");
            crs.execute();
            while (crs.next()) {
                System.out.println(crs.getString("Name"));
            }

            // Inserting rows
            crs.moveToInsertRow();
            crs.updateInt("Id", 5);
            crs.updateString("Name", "E");
            crs.insertRow();

            //Thread.sleep(60000);
            crs.acceptChanges(c); // Updating Data Sources

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【问题讨论】:

    标签: java mysql database jakarta-ee jdbc


    【解决方案1】:

    您会发现打印出有关异常的所有信息很有帮助。如果您捕获的是 SQLException 而不是一般的异常(通常您应该捕获特定的异常),您将可以访问更多信息,包括 SQL state and error codes

    我相信在这种情况下,您会发现这是与连接设置为自动提交更改有关的错误。我相信 CachedRowSet 在您初始化并执行其命令时正在建立自己的连接。它不知道您创建的连接“c”,直到您将它传递给acceptChanges。我认为这意味着 crs 的连接同时将 autoCommit 设置为 true。

    尝试将 ?relaxAutoCommit=true 添加到您的 url 字符串中,如下所示:

    crs.setUrl("jdbc:mysql://localhost:3306/test?relaxAutoCommit=true");
    

    您无需向其传递 Connection 即可接受更改,因为它有自己的。事实上,您不需要创建另一个连接,它会一直保持打开状态。 CachedRowSet 的全部意义在于您在进行更改时不会保持连接打开。

    【讨论】:

    • 它不起作用。你能修改我的代码以准确反映它是如何工作的吗?可能是我做错了什么。
    • 我认为relaxAutoCommit 是为了别的。我明白你的想法并同意它,但在我的情况下它也没有帮助。根据我的阅读,它适用于不支持事务的 MySQL 版本(请参阅dev.mysql.com/doc/connector-j/5.1/en/…
    【解决方案2】:

    声明crs.moveToCurrentRow()必须添加在crs.insertRow()之后和crs.acceptChanges(c)之前

    例如:

     // Inserting rows
    crs.moveToInsertRow();
    crs.updateInt("Id", 5);
    crs.updateString("Name", "E");
    crs.insertRow();
    crs.moveToCurrentRow(); // NEW STATEMENT
    crs.acceptChanges(c); // Updating Data Sources
    

    欲了解更多信息,请访问:http://docs.oracle.com/javase/tutorial/jdbc/basics/cachedrowset.html#inserting-and-deleting-rows

    【讨论】:

    • 非常感谢。那行得通。但我不明白为什么需要该声明。如果你不介意,你能解释一下这句话的意义吗?
    • 当您调用 moveToInsertRow 时,您无法接受更改,您必须退回到记住的位置。调用 moveToInsertRow 方法时,方法 moveToCurrentRow 将光标移动到光标所在的行。
    • 例如,您可以在遍历 RowSet 时插入行:while (crs.next()) {/*在此处插入行*/}。因此,如果您不移回当前行,您将无法更进一步,因为用于插入的行不是您的 RowSet 的一部分。调用 moveToInsertRow 类似于进入某个特殊的房间做某事,而不是您必须离开房间才能继续迭代。
    • 非常感谢 Dmytro。这解释了一切:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 2016-08-12
    • 2021-09-14
    • 2014-04-12
    • 1970-01-01
    相关资源
    最近更新 更多