我正在尝试实现一个简单的GUI应用程序来处理数据库记录。它将包含记录视图和编辑它们的可能性。以下是我的代码的样子:
class MainPanel extends JPanel {
private CachedRowSet crs;
private List<JTextField> fields = new LinkedList<>();
MainPanel() {
try {
//Fill result set with data
crs = new CachedRowSetImpl();
crs.setUrl("jdbc:postgresql:testdb");
crs.setUsername("username");
crs.setPassword("password");
crs.setCommand("SELECT * FROM products");
crs.execute();
//Create text fields with labels
ResultSetMetaData meta = crs.getMetaData();
for (int a = 1; a <= meta.getColumnCount(); a++) {
JTextField field = new JTextField(10);
add(new JLabel(meta.getColumnLabel(a)));
fields.add(field);
add(field);
}
//Fill fields on startup
crs.next();
updateFields();
//Buttons
JButton nextButton = new JButton("Next");
nextButton.addActionListener(...);
add(nextButton);
JButton prevButton = new JButton("Previous");
prevButton.addActionListener(...);
add(prevButton);
JButton saveButton = new JButton("Save changes");
saveButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
try {
for (int a=0; a<fields.size(); a++) {
crs.updateString(a+1, fields.get(a).getText());
}
crs.acceptChanges();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
});
add(saveButton);
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
private void updateFields() throws SQLException {
for (int a = 0; a < fields.size(); a++) {
fields.get(a).setText(crs.getString(a + 1).trim());
}
}
}
下一步和上一步正常工作。但是在尝试保存记录时我遇到了异常。堆栈跟踪如下:
org.postgresql.util.PSQLException: Cannot commit when autoCommit is enabled.
at org.postgresql.jdbc2.AbstractJdbc2Connection.commit(AbstractJdbc2Connection.java:705)
at com.sun.rowset.internal.CachedRowSetWriter.commit(CachedRowSetWriter.java:1396)
at com.sun.rowset.CachedRowSetImpl.acceptChanges(CachedRowSetImpl.java:893)
at test.MainPanel$3.actionPerformed(MainPanel.java:85)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
...
如何防止此异常?什么是自动提交?我知道Connection类有一个选项可以将它设置为false,但我不想使用Connection类。我想用CachedResultSet完成所有事情。我该如何解决这个问题?
答案 0 :(得分:2)
添加
crs.getConnection ().setAutoCommit (false);
答案 1 :(得分:1)
将以下内容添加到URL:
的末尾"?relaxAutoCommit=true"
答案 2 :(得分:0)
我遇到了同样的问题--CachedRowSetImpl.acceptChanges()无法关闭自动提交,当它提交更改时会抛出异常,因为它们已经单独提交。
这可能是因为PostgreSQL对自动提交有点挑剔。 PostgreSQL不允许通过SQL语句关闭自动提交(虽然它在早期就已经完成)。相反,任何必须作为组提交的SQL语句都必须夹在SQL语句BEGIN和COMMIT之间。 PostgreSQL的JDBC驱动程序确实支持Connection.setAutoCommit(false),但我敢打赌这只是提示驱动程序在幕后创建一个BEGIN-COMMIT三明治。我的猜测是CachedRowSetImpl.acceptChanges()试图使用SQL语句来关闭自动提交而不是使用setAutoCommit(false),这就是它失败的原因。
我找到解决此问题的唯一方法是创建临时连接,关闭自动提交,并将连接传递给acceptChanges的一个参数版本。所以不要这样:
crs.acceptChanges()
你会有这样的事情:
try (Connection con
= DriverManager.getConnection(url, username, password)) {
con.setAutoCommit(false);
crs.acceptChanges(con);
}
这确实需要使用您尝试避免的Connection类,但可能没有任何替代方法(不使用JDBC)。您不能使用CachedRowSetImpl.getConnection(),因为它只检索外部创建然后传入的连接。您无法通过url指定要关闭自动提交,因为PostgreSQL不允许这样做。如果可以更新CachedRowSetImpl.acceptChanges()以便它自己成功关闭自动提交,那就太好了。但是,这似乎有点不太可能,因为我的编译器警告可能会在将来的版本中删除CachedRowSetImpl。
答案 3 :(得分:0)
使用CachedRowset时遇到了类似的问题。我正在使用MySQL数据库。 在尝试许多解决方案时我终于想出了两个对我有用的解决方法。我想在这里提一下:
使用Connection对象并将其传递给execute(con)
和acceptChanges(con)
方法。同时设置setAutoCommit(false)
。
例如:
Connection conn = DriverManager.getConnection(databaseUrl, username, password);
conn.setAutoCommit(false);
CachedRowSet rowSet=new CachedRowSetImpl();
rowSet.setCommand("SELECT * FROM tableName");
int [] keys = {1}; // Set column 1 as the key column in the RowSet
rowSet.setKeyColumns(keys);
rowSet.execute(conn); // Execute on connection
rowSet.moveToInsertRow();
rowSet.updateInt(1, 89); // Use column number
rowSet.updateString(2, "Programming");
rowSet.updateInt(3, 77);
rowSet.insertRow();
// Need to move away from insert row before apply changes
rowSet.moveToCurrentRow();
// Reconnect to data source to apply change in the RowSet.
rowSet.acceptChanges(conn); // On non-autocommit Connection
注意:在这种情况下,您不需要设置CachedRowset的属性,如setURL()
,setUser()
和setPassword()
。因为CachedRowset对象使用Connection对象连接到已手动创建并使用autocommit=false
如URL
所述,将?relaxAutoCommit=true
添加到bobby-paulose
Example:
String url = "jdbc:mysql://localhost:3306/DatabaseName?relaxAutoCommit=true";