如何使用 PostgreSQL JDBC 从数据库中读取 ArrayList<String> 字段
How to read ArrayList<String> field from database with PostgreSQL JDBC
我在获取数据库中存储的 ArrayList<String>
作为 VARCHAR[]
的值时遇到问题。
不知何故,当我调试时,我可以看到从数据库返回的值是:
我希望通过将 ArrayList<String>
转换为 VARCHAR[]
来存储它,当从数据库中读取时,我希望将 VARCHAR[]
转换为 ArrayList<String>
代码:
public Message<ArrayList<String>> getPlayersInSession(Object data) throws SQLException, ClassNotFoundException {
String sessionCode = (String) data;
Session session = PostgreSQLJDBC.sessionJDBCInstance().getSession(sessionCode);
//session.getPlayers() is the problem I have
return new Message<>(Message.RequestCode.RECEIVE_PLAYERS_IN_SESSION, session.getPlayers());
(Message.RequestCode.RECEIVE_PLAYERS_IN_SESSION, players);
}
public class Session {
private int _id;
private String _code;
private ArrayList<String> _players;
private ArrayList<Pair<String, String>> _leaderboard;
public Session() {
_code = "";
_players = new ArrayList<>();
_leaderboard = new ArrayList<>();
}
...
}
public class SessionJDBC implements SessionSQL {
private final Connection _connection;
public SessionJDBC(String url, String user, String password) throws ClassNotFoundException, SQLException {
Class.forName("org.postgresql.Driver");
_connection = DriverManager.getConnection(url, user, password);
if (!sessionTableExists()) createTable();
}
@Override
public void createTable() throws SQLException {
String sql = "CREATE TABLE session(" +
"id SERIAL PRIMARY KEY," +
"code VARCHAR," +
"players VARCHAR[]," +
"leaderboard VARCHAR[]" +
")";
PreparedStatement ps = _connection.prepareStatement(sql);
ps.executeUpdate();
}
@Override
public void addSession(Session session) throws SQLException {
String sql = "INSERT INTO session(code, players, leaderboard)"
+ "VALUES (?,?,?)";
PreparedStatement ps = _connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, session.getCode());
ps.setArray(2, _connection.createArrayOf("VARCHAR", session.getPlayers().toArray()));
ps.setArray(3, _connection.createArrayOf("VARCHAR", session.getLeaderboard().toArray()));
ps.executeUpdate();
ResultSet generatedKeys = ps.getGeneratedKeys();
if (generatedKeys.next()) {
session.setId(generatedKeys.getInt(1));
}
}
@Override
public void removeSession(Session session) throws SQLException {
String sql = "DELETE FROM session WHERE id = ?";
PreparedStatement ps = _connection.prepareStatement(sql);
ps.setInt(1, session.getId());
ps.executeUpdate();
}
@Override
public Session getSession(String code) throws SQLException {
return getAllSessions().stream().filter(session -> session.getCode().equals(code)).findFirst().orElse(null);
}
@Override
public ArrayList<Session> getAllSessions() throws SQLException {
ArrayList<Session> array = new ArrayList<>();
ResultSet result = _connection.prepareStatement("SELECT * FROM session").executeQuery();
while (result.next()) {
Session session = new Session();
session.setCode(result.getString("code"));
session.setId(result.getInt("id"));
session.setPlayers(new ArrayList(Collections.singletonList(result.getArray("players"))));
session.setLeaderboard(new ArrayList(Collections.singletonList(result.getArray("leaderboard"))));
array.add(session);
}
result.close();
return array;
}
@Override
public boolean sessionTableExists() throws SQLException {
DatabaseMetaData dbm = _connection.getMetaData();
ResultSet tables = dbm.getTables(null, null, "session", null);
return tables.next();
}
}
我不知道代码示例是如何编译的,因为调试器中显示的 ArrayList 实际上是 ArrayList<PgArray>
类型而不是 ArrayList<String>
。
问题出现在这些行中:
session.setPlayers(new ArrayList(Collections.singletonList(result.getArray("players"))));
session.setLeaderboard(new ArrayList(Collections.singletonList(result.getArray("leaderboard"))));
首先 result.getArray("players")
返回 java.sql.Array object, more specifically a PgArray 实现。要获取真正的底层数据,您需要做的是:
(String[])result.getArray("players").getArray();
下一个问题是您正在使用 Collections.singletonList()
。它的作用是生成一个只有一个元素的 ArrayList。相反,您应该使用 Arrays.asList
。完整解决方案:
session.setPlayers(new ArrayList(Arrays.asList((String[])result.getArray("players").getArray)));
session.setLeaderboard(new ArrayList(Arrays.asList((String[])result.getArray("leaderboard").getArray)));
关于此代码的另一件有趣的事情是,您正在 selecting 来自 table 的所有行,然后通过流式处理结果在内存中进行过滤。为什么不在 SQL 查询的 code
字段上 select?
我在获取数据库中存储的 ArrayList<String>
作为 VARCHAR[]
的值时遇到问题。
不知何故,当我调试时,我可以看到从数据库返回的值是:
我希望通过将 ArrayList<String>
转换为 VARCHAR[]
来存储它,当从数据库中读取时,我希望将 VARCHAR[]
转换为 ArrayList<String>
代码:
public Message<ArrayList<String>> getPlayersInSession(Object data) throws SQLException, ClassNotFoundException {
String sessionCode = (String) data;
Session session = PostgreSQLJDBC.sessionJDBCInstance().getSession(sessionCode);
//session.getPlayers() is the problem I have
return new Message<>(Message.RequestCode.RECEIVE_PLAYERS_IN_SESSION, session.getPlayers());
(Message.RequestCode.RECEIVE_PLAYERS_IN_SESSION, players);
}
public class Session {
private int _id;
private String _code;
private ArrayList<String> _players;
private ArrayList<Pair<String, String>> _leaderboard;
public Session() {
_code = "";
_players = new ArrayList<>();
_leaderboard = new ArrayList<>();
}
...
}
public class SessionJDBC implements SessionSQL {
private final Connection _connection;
public SessionJDBC(String url, String user, String password) throws ClassNotFoundException, SQLException {
Class.forName("org.postgresql.Driver");
_connection = DriverManager.getConnection(url, user, password);
if (!sessionTableExists()) createTable();
}
@Override
public void createTable() throws SQLException {
String sql = "CREATE TABLE session(" +
"id SERIAL PRIMARY KEY," +
"code VARCHAR," +
"players VARCHAR[]," +
"leaderboard VARCHAR[]" +
")";
PreparedStatement ps = _connection.prepareStatement(sql);
ps.executeUpdate();
}
@Override
public void addSession(Session session) throws SQLException {
String sql = "INSERT INTO session(code, players, leaderboard)"
+ "VALUES (?,?,?)";
PreparedStatement ps = _connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, session.getCode());
ps.setArray(2, _connection.createArrayOf("VARCHAR", session.getPlayers().toArray()));
ps.setArray(3, _connection.createArrayOf("VARCHAR", session.getLeaderboard().toArray()));
ps.executeUpdate();
ResultSet generatedKeys = ps.getGeneratedKeys();
if (generatedKeys.next()) {
session.setId(generatedKeys.getInt(1));
}
}
@Override
public void removeSession(Session session) throws SQLException {
String sql = "DELETE FROM session WHERE id = ?";
PreparedStatement ps = _connection.prepareStatement(sql);
ps.setInt(1, session.getId());
ps.executeUpdate();
}
@Override
public Session getSession(String code) throws SQLException {
return getAllSessions().stream().filter(session -> session.getCode().equals(code)).findFirst().orElse(null);
}
@Override
public ArrayList<Session> getAllSessions() throws SQLException {
ArrayList<Session> array = new ArrayList<>();
ResultSet result = _connection.prepareStatement("SELECT * FROM session").executeQuery();
while (result.next()) {
Session session = new Session();
session.setCode(result.getString("code"));
session.setId(result.getInt("id"));
session.setPlayers(new ArrayList(Collections.singletonList(result.getArray("players"))));
session.setLeaderboard(new ArrayList(Collections.singletonList(result.getArray("leaderboard"))));
array.add(session);
}
result.close();
return array;
}
@Override
public boolean sessionTableExists() throws SQLException {
DatabaseMetaData dbm = _connection.getMetaData();
ResultSet tables = dbm.getTables(null, null, "session", null);
return tables.next();
}
}
我不知道代码示例是如何编译的,因为调试器中显示的 ArrayList 实际上是 ArrayList<PgArray>
类型而不是 ArrayList<String>
。
问题出现在这些行中:
session.setPlayers(new ArrayList(Collections.singletonList(result.getArray("players"))));
session.setLeaderboard(new ArrayList(Collections.singletonList(result.getArray("leaderboard"))));
首先 result.getArray("players")
返回 java.sql.Array object, more specifically a PgArray 实现。要获取真正的底层数据,您需要做的是:
(String[])result.getArray("players").getArray();
下一个问题是您正在使用 Collections.singletonList()
。它的作用是生成一个只有一个元素的 ArrayList。相反,您应该使用 Arrays.asList
。完整解决方案:
session.setPlayers(new ArrayList(Arrays.asList((String[])result.getArray("players").getArray)));
session.setLeaderboard(new ArrayList(Arrays.asList((String[])result.getArray("leaderboard").getArray)));
关于此代码的另一件有趣的事情是,您正在 selecting 来自 table 的所有行,然后通过流式处理结果在内存中进行过滤。为什么不在 SQL 查询的 code
字段上 select?