我正在创建一个程序来管理 MySQL 服务器。我有一个工作用户界面和代码,可以按预期向数据库添加新条目。下图是我正在使用的原始 GUI,对于这个问题来说重要的部分是表格框,它将在数据库工作时显示数据库的条目。
我用于读取数据库内容的代码可以正常工作。该程序的结构使得我可以为界面、场景 Controller 和 SQL 命令提供单独的类。我正在处理的问题是,我可以从数据库中提取所需的数据,但访问场景 Controller 类以将其写入数据库根本不起作用。
相关代码片段包含在下面。
SQL 函数:
public ResultSet readDataBase() throws Exception{
try {
// Establish connection to server
Class.forName("com.mysql.cj.jdbc.Driver");
connect=DriverManager.getConnection("jdbc:mysql://localhost/library?"+"user=tempUser&password=12345");
statement=connect.createStatement();
// Execute query and write the results
resultSet=statement.executeQuery("select * from library.books");
return resultSet;
// writeResultSet(resultSet);
} catch (Exception e){
throw e;
} finally {
close();
}
}
场景 Controller 代码:
public void fillTable() throws SQLException{
ResultSet resultSet=null;
try {
resultSet=commands.readDataBase();
while(resultSet.next()) {
String title = resultSet.getString("title");
String author = resultSet.getString("author");
String genre = resultSet.getString("genre");
String format = resultSet.getString("format");
String isbn = resultSet.getString("isbn");
System.out.println("Title: " + title);
System.out.println("Author: " + author);
System.out.println("Genre: " + genre);
System.out.println("Format: " + format);
System.out.println("ISBN: " + isbn);
System.out.println();
}
}catch (Exception e){
e.printStackTrace();
}
}
场景 Controller block 中代码的目的只是暂时测试并读取结果集。稍后将添加用于将结果中的数据写入各自表的写入代码。选择这段代码是因为我最初将它放在 SQL 函数类中并且它在那里工作,所以我知道这段代码很好并且完成了它的工作。
但是,每当我运行代码时,我都会收到此错误结果。
java.sql.SQLException: Operation not allowed after ResultSet closed
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.result.ResultSetImpl.checkClosed(ResultSetImpl.java:445)
at com.mysql.cj.jdbc.result.ResultSetImpl.next(ResultSetImpl.java:1726)
at library.test.windows.interfaceSceneController.fillTable(interfaceSceneController.java:108)
at library.test.windows.winInterface.main(winInterface.java:33)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
我之前已经对此进行了一些阅读,但我能找到的唯一真正相关的信息来源是在这个 post 中。从七多年前开始。该问题的答案提到使用 JavaBeans 作为将信息放入中间的位置,但随后在示例代码中使用了一个名为“Biler”的类。除了他的帖子之外,我在任何地方都找不到任何对 Biler 的引用,而我的 IDE(IntelliJ,如果相关的话)根本无法识别它。我一直在使用 JavaBeans 进行一些实验,但我不确定它是否能解决我的问题。
总而言之,我的问题是这样的。为了将 ResultSet 从访问 SQL Server 的函数正确传递到包含将其写入界面中的表的代码的类,我需要做什么?我知道这一定有可能,但我似乎无法弄清楚。
最佳答案
您的数据库访问代码应与用户界面代码完全分开。 UI 不应处理 Activity 的 ResultSet
。
您需要从结果集中复制数据,或使用实用程序来执行此操作。
CachedRowSet
一个RowSet
可能是解决方案。该接口(interface)扩展了 ResultSet
。请参阅Java Tutorials Oracle 的解释。
您可以使用CachedRowSet
接口(interface)将结果集数据的副本保留在内存中,与数据库分离。 Oracle 提供了一种实现,其他供应商(例如您的 JDBC driver)也可能提供这种实现。 .
CachedRowSet
实现与数据库断开。相反,ResultSet
维护数据库连接(问题的根源)。引用 Javadoc:
A CachedRowSet object is a container for rows of data that caches its rows in memory, which makes it possible to operate without always being connected to its data source. Further, it is a JavaBeans™ component and is scrollable, updatable, and serializable.
该接口(interface)通过更多接口(interface)进行了扩展。
POJO
普通旧 Java 对象是另一种选择,将 ResultSet
中每行的每个字段复制到 Java 对象的属性中。
您可以在实例化记录时简单地循环结果集。或者您可以使用各种框架中的任何一种来提供帮助。
记录
使用 Java 16 中新增的记录功能(现已预览)时,为此类 POJO 定义类要简单得多 in Java 15 。构造函数、getter、toString、equals 和 hashCode 都是由编译器合成的。您只需声明属性即可。
记录可以声明为独立类、嵌套类,甚至可以在方法中本地声明。
关于java - 将 ResultSet 返回给另一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63119694/