將結果集轉換為映射
一、簡介
Java 應用程式廣泛使用 Java 資料庫連接 (JDBC) API 來連接資料庫並在資料庫上執行查詢。 ResultSet
是這些查詢擷取的資料的表格表示形式。
在本教學中,我們將學習如何將 JDBC ResultSet
的資料轉換為Map
。
2. 設定
我們將編寫一些測試案例來實現我們的目標。我們的資料來源將是 H2 資料庫。 H2 是一個快速、開源、支援 JDBC API 的記憶體資料庫。讓我們新增相關的Maven 依賴項:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
資料庫連線準備就緒後,我們將編寫一個方法來為測試案例進行初始資料設定。為了實現這一點,我們先建立一個 JDBC Statement
,然後使用它來建立一個名為employee
的資料庫表。 employee
表由名為empId, empName,
和empCity
的欄位組成,這些欄位將保存有關員工的 ID、姓名和城市的資訊。現在,我們可以使用Statement.execute()
方法在表中插入範例資料:
void initialDataSetup() throws SQLException {
Statement statement = connection.createStatement();
String sql = "CREATE TABLE employee ( " +
"empId INTEGER not null, " +
"empName VARCHAR(50), " +
"empCity VARCHAR(50), " +
"PRIMARY KEY (empId))";
statement.execute(sql);
List<String> sqlQueryList = Arrays.asList(
"INSERT INTO employee VALUES (1, 'Steve','London')",
"INSERT INTO employee VALUES (2, 'John','London')",
"INSERT INTO employee VALUES (3, 'David', 'Sydney')",
"INSERT INTO employee VALUES (4, 'Kevin','London')",
"INSERT INTO employee VALUES (5, 'Jade', 'Sydney')");
for (String query: sqlQueryList) {
statement.execute(query);
}
}
3. ResultSet
集到Map
現在樣本資料已存在於資料庫中,我們可以查詢它以進行提取。查詢資料庫以ResultSet
的形式給出輸出。我們的目標是將此ResultSet
中的資料轉換為Map
,其中鍵是城市名稱,值是該城市中的員工姓名清單。
3.1.使用Java 7
我們先從資料庫連線建立一個PreparedStatement
,並向其提供一個SQL 查詢。然後,我們可以使用PreparedStatement.executeQuery()
方法來取得ResultSet
。
現在,我們可以迭代ResultSet
資料並單獨取得列資料。為此,我們可以使用ResultSet.getString()
方法,將employee
表的列名傳遞給該方法。之後,我們可以使用Map.containsKey()
方法檢查地圖是否已包含該城市名稱的條目。如果沒有找到該城市的鍵,我們將新增一個條目,其中城市名稱作為鍵,空的ArrayList
作為值。然後,我們將員工姓名加入該城市的員工姓名清單:
@Test
void whenUsingContainsKey_thenConvertResultSetToMap() throws SQLException {
ResultSet resultSet = connection.prepareStatement(
"SELECT * FROM employee").executeQuery();
Map<String, List<String>> valueMap = new HashMap<>();
while (resultSet.next()) {
String empCity = resultSet.getString("empCity");
String empName = resultSet.getString("empName");
if (!valueMap.containsKey(empCity)) {
valueMap.put(empCity, new ArrayList<>());
}
valueMap.get(empCity).add(empName);
}
assertEquals(3, valueMap.get("London").size());
}
3.2.使用Java 8
Java 8 引入了 lambda 表達式和預設方法的概念。我們可以在實作中利用它們來簡化輸出映射中新鍵的輸入。我們可以使用Map
類別的computeIfAbsent()
方法,該方法有兩個參數:一個鍵和一個映射函數。如果找到該鍵,則傳回相關值;否則,它將使用映射函數建立預設值並將其作為新的鍵值對儲存在映射中。之後我們可以將員工的姓名加入清單。
這是使用 Java 8 的先前測試案例的修改版本:
@Test
void whenUsingComputeIfAbsent_thenConvertResultSetToMap() throws SQLException {
ResultSet resultSet = connection.prepareStatement(
"SELECT * FROM employee").executeQuery();
Map<String, List<String>> valueMap = new HashMap<>();
while (resultSet.next()) {
String empCity = resultSet.getString("empCity");
String empName = resultSet.getString("empName");
valueMap.computeIfAbsent(empCity, data -> new ArrayList<>()).add(empName);
}
assertEquals(3, valueMap.get("London").size());
}
3.3.使用 Apache Commons DbUtils
Apache Commons DbUtils 是一個第三方函式庫,為 JDBC 作業提供附加和簡化的功能。它提供了一個名為ResultSetHandler
的有趣接口,該接口使用 JDBC ResultSet
作為輸入,並允許我們將其轉換為應用程式期望的所需物件。此外,該程式庫使用QueryRunner
類別在資料庫表上執行 SQL 查詢。 QueryRunner
。 query()
方法將資料庫連接、SQL 查詢和ResultSetHandler
作為輸入並直接傳回預期的格式。
讓我們來看看一個如何使用ResultSetHandler
從ResultSet
建立Map
的範例:
@Test
void whenUsingDbUtils_thenConvertResultSetToMap() throws SQLException {
ResultSetHandler <Map<String, List<String>>> handler = new ResultSetHandler <Map <String, List<String>>>() {
public Map<String, List<String>> handle(ResultSet resultSet) throws SQLException {
Map<String, List<String>> result = new HashMap<>();
while (resultSet.next()) {
String empCity = resultSet.getString("empCity");
String empName = resultSet.getString("empName");
result.computeIfAbsent(empCity, data -> new ArrayList<>()).add(empName);
}
return result;
}
};
QueryRunner run = new QueryRunner();
Map<String, List<String>> valueMap = run.query(connection, "SELECT * FROM employee", handler);
assertEquals(3, valueMap.get("London").size());
}
4。結論
總而言之,我們研究了從ResultSet
聚合資料並使用 Java 7、Java 8 和 Apache DbUtils
函式庫將其轉換為Map
的幾種方法。
與往常一樣,本文的完整程式碼可以在 GitHub 上找到。