【问题标题】:Can't load objects from a ResultSet in Java无法从 Java 中的 ResultSet 加载对象
【发布时间】:2018-03-24 20:10:09
【问题描述】:

我在从 SQLite 数据库加载对象时遇到问题。

首先,这是我的表定义:

CREATE TABLE MyTable (
  rowid INTEGER PRIMARY KEY,
  data BLOB
);

这是我要存储和重新加载的简单类:

public class MyHashMap extends HashMap<String, Integer> {
    private static final long serialVersionUID = 0L;
}

然后我用一些数据填充地图,并使用 SQL INSERT 语句将其存储在数据库中。一切正常,如果我执行 SELECT(使用 sqlite3 命令行客户端),我将看到正确的信息。

现在我正在使用 java.sql 包来加载对象:

String sql = "SELECT data FROM MyTable WHERE rowid = 1";
MyHashMap map = null;

try {
  try (Statement stmt = db.createStatement()) {
    try (ResultSet rs = stmt.executeQuery(sql)) {
      if (rs.next()) {
        map = rs.getObject("data", MyHashMap.class);
      }
    }
  }
} catch (Exception e) {
  e.printStackTrace();
}

没有抛出异常,但我的地图变量为空。我调试了程序,可以说getObject方法按预期调用了。

【问题讨论】:

  • 开启调试模式,将查询显示为真,查看已执行的查询
  • 我阅读了链接的线程,但它对我没有帮助,因为我认为不可能将 Blob 接口“转换”为我的 HashMap 对象。
  • 可能查询得到了空值。您尝试打印查询结果了吗?

标签: java sqlite


【解决方案1】:

首先,你对MyHashMap的定义不正确

public class MyHashMap extends HashMap<Integer, String> {
    private static final long serialVersionUID = 0L;
}

不过,主要问题是 SQL 不存储 Java 对象。它只存储由字段组成的记录行。您需要将这些记录一一阅读,并将它们存储在您的地图中。大致如下:

MyHashMap map = new MyHashMap();
final String sql = "SELECT rowid, data FROM MyTable";
try (final Statement stmt = connection.createStatement;
        final ResultSet rs = stmt.executeQuery(sql)) {
    while (rs.next()) {
        map.put(rs.getInt(1), rs.getString(2));
    }
 }

请注意,将Blob 读入String 很有可能会失败。通常,JDBC 驱动程序足够聪明,可以转换数据类型,但如果您的 blob 中有原始二进制数据,则无法将其读入字符串。您将需要 getBlob 方法,并处理生成的对象。但我无法从您的代码中看出您将在该 blob 中存储什么。

【讨论】:

  • 我想你误会了:我对 HashMap 的定义是绝对正确的。键是字符串,值是计数器。然后:不,我不想读取 HashMap 中的 rowid 和字符串。我的想法是将整个 HashMap 存储在一个 BLOB 中并从那里重新加载它。我在文档中读到,这可以通过可序列化的类来实现。那么 rowid 只是我的记录的自动增量。
  • 然后,问题就出现了,为什么要将 Java 对象存储在数据库中。这不是关系数据库的用途。但是由于您已经解决了自己的问题,请将其添加为该问题的答案,并将其标记为已接受的答案。它会帮助其他人。
【解决方案2】:

好的,我找到了解决方法,方法如下:

private Object getObjectFromBlob(ResultSet rs, String columnName)
    throws ClassNotFoundException, IOException, SQLException {
  InputStream binaryInput = rs.getBinaryStream(columnName);
  if (binaryInput == null || binaryInput.available() == 0) {
    return null;
  }

  ObjectInputStream in = new ObjectInputStream(binaryInput);
  try {
    return in.readObject();
  } finally {
    in.close();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 2011-02-12
    • 1970-01-01
    相关资源
    最近更新 更多