本文示範如何建立使用 Java 和 JDBC 的範例應用程式,以在 Azure HorizonDB (Preview) 中儲存及擷取資訊。
JDBC 是連接傳統關聯式資料庫的標準 Java API。
本文的步驟包括 PostgreSQL 認證。
PostgreSQL 認證使用儲存在 PostgreSQL 中的帳號,而你需要自己管理密碼的輪替。
先決條件
- 一個 Azure 帳戶。 如果您沒有帳戶,請取得免費試用帳戶。
- Azure Cloud Shell 或 Azure CLI。 使用 Azure Cloud Shell,這樣你就能自動驗證,並且能使用所有需要的工具。
- 支援的 Java 開發套件,版本 8(包含於 Cloud Shell)。
- Apache Maven 建置工具。
準備工作環境
首先,使用以下指令來設定一些環境變數。
export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_CLUSTER_NAME=<YOUR_DATABASE_CLUSTER_NAME>
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_POSTGRESQL_ADMIN_USERNAME=demo
export AZ_POSTGRESQL_ADMIN_PASSWORD=<YOUR_POSTGRESQL_ADMIN_PASSWORD>
export AZ_POSTGRESQL_NON_ADMIN_USERNAME=demo-non-admin
export AZ_POSTGRESQL_NON_ADMIN_PASSWORD=<YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>
export AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>
用本文中使用的以下值替換預留位置:
-
<YOUR_DATABASE_CLUSTER_NAME>:你Azure HorizonDB 叢集的名稱,應該在你的 Azure 訂閱與資源群組中獨一無二。 -
<YOUR_DATABASE_NAME>:你在 HorizonDB 叢集Azure中使用的資料庫名稱。 -
<YOUR_AZURE_REGION>:要使用的 Azure 區域。 你可以預設使用australiaeast,但設定一個離你住處更近的區域。 您可以輸入az account list-locations來查看可用區域的完整清單。 -
<YOUR_POSTGRESQL_ADMIN_PASSWORD>和<YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>:你Azure HorizonDB 叢集的密碼。 該密碼至少要有八個字元。 這些字元應屬於下列三種類別:英文大寫字母、英文小寫字母、數字 (0-9) 及非英數字元 (!、$、#、% 等等)。 -
<YOUR_LOCAL_IP_ADDRESS>: 你本機電腦的 IP 位址,從它上執行 Spring Boot 應用程式。 一個方便找到它的方法是打開 whatismyip.akamai.com。
接下來,使用下列命令建立資源群組:
az group create \
--name $AZ_RESOURCE_GROUP \
--location $AZ_LOCATION \
--output tsv
建立 Azure HorizonDB 叢集
Note
資源名稱(例如資料表名稱、資料庫名稱)及資源標籤中,請勿包含任何個人、敏感或機密資訊。 你在這些欄位輸入的資料不算是客戶資料。
以下章節將說明如何建立與配置您的資料庫叢集。
建立 Azure HorizonDB 叢集
設定系統管理使用者
首先,建立一個受管理的 Azure HorizonDB 實例。
Note
如需深入了解如何建立 Azure HorizonDB 的詳細資訊,請參閱 建立 Azure HorizonDB 叢集。
az horizondb create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_CLUSTER_NAME \
--location $AZ_LOCATION \
--version 17 \
--administrator-login $AZ_POSTGRESQL_ADMIN_USERNAME \
--administrator-login-password $AZ_POSTGRESQL_ADMIN_PASSWORD \
--v-cores 2 \
--yes \
--output tsv
此指令會建立一個小型的 Azure HorizonDB 叢集。
為你的 Azure HorizonDB 實例設定防火牆規則
Azure HorizonDB 實例預設是安全的。 他們有防火牆,會封鎖所有進來的連線。 要使用你的資料庫,可以新增防火牆規則,讓你的本地 IP 位址存取資料庫伺服器。
由於您在本文開頭設定了本機 IP 位址,因此您可以執行下列命令來開啟伺服器的防火牆:
az horizondb firewall-rule create \
--resource-group $AZ_RESOURCE_GROUP \
--cluster-name $AZ_DATABASE_CLUSTER_NAME \
--firewall-rule-name $AZ_DATABASE_CLUSTER_NAME-database-allow-local-ip \
--start-ip-address $AZ_LOCAL_IP_ADDRESS \
--end-ip-address $AZ_LOCAL_IP_ADDRESS \
--output tsv
如果你是從 Windows 電腦上的 Windows 子系統 Linux 版(WSL)連接到 Azure HorizonDB 叢集,你需要在防火牆上新增 WSL 主機 ID。
透過 WSL 執行以下指令,取得你主機的 IP 位址:
cat /etc/resolv.conf
複製術語 nameserver後面的 IP 位址,然後使用以下指令為 WSL IP 位址設定環境變數:
AZ_WSL_IP_ADDRESS=<the-copied-IP-address>
然後,使用下列命令將伺服器的防火牆開啟至 WSL 型應用程式:
az horizondb firewall-rule create \
--resource-group $AZ_RESOURCE_GROUP \
--cluster-name $AZ_DATABASE_CLUSTER_NAME \
--firewall-rule-name $AZ_DATABASE_CLUSTER_NAME-database-allow-local-ip \
--start-ip-address $AZ_WSL_IP_ADDRESS \
--end-ip-address $AZ_WSL_IP_ADDRESS \
--output tsv
建立 Azure HorizonDB 資料庫
建立一個名為 create_database.sql 的 SQL 腳本,在叢集中建立新的資料庫。 新增以下內容並將檔案儲存在本地:
cat << EOF > create_database.sql
CREATE DATABASE "$AZ_DATABASE_NAME";
EOF
執行此指令取得您的 Azure HorizonDB 完全限定網域名稱,並複製 clusterName 值:
az horizondb show \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_CLUSTER_NAME \
--query "{clusterName:properties.fullyQualifiedDomainName, adminUser:properties.administratorLogin}" \
--output table
複製該 clusterName 值並依以下指令使用:
AZ_HORIZONDB_FQDN=<the-copied-clusterName-value>
接著執行以下指令執行 SQL 腳本並建立資料庫:
psql "host=$AZ_HORIZONDB_FQDN user=$AZ_POSTGRESQL_ADMIN_USERNAME dbname=$AZ_DATABASE_NAME port=5432 password=$AZ_POSTGRESQL_ADMIN_PASSWORD sslmode=require" < create_database.sql
接著,執行以下指令刪除暫存的 SQL 腳本檔案:
rm create_database.sql
建立一個 Azure HorizonDB 非管理員使用者並授予權限
接著,建立一個非管理員使用者,並授予資料庫所有權限。
建立一個名為 create_user.sql 的 SQL 腳本來建立非管理員使用者。 新增以下內容並將檔案儲存在本地:
cat << EOF > create_user.sql
CREATE ROLE "$AZ_POSTGRESQL_NON_ADMIN_USERNAME" WITH LOGIN PASSWORD '$AZ_POSTGRESQL_NON_ADMIN_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE $AZ_DATABASE_NAME TO "$AZ_POSTGRESQL_NON_ADMIN_USERNAME";
EOF
接著執行以下指令執行 SQL 腳本並建立 Microsoft Entra 非管理員使用者:
psql "host=$AZ_HORIZONDB_FQDN user=$AZ_POSTGRESQL_ADMIN_USERNAME dbname=$AZ_DATABASE_NAME port=5432 password=$AZ_POSTGRESQL_ADMIN_PASSWORD sslmode=require" < create_user.sql
接著,執行以下指令刪除暫存的 SQL 腳本檔案:
rm create_user.sql
建立新的 Java 專案
使用你喜愛的 IDE,使用 Java 8 或更新版本建立一個新的 Java 專案。 在根目錄中新增一個包含以下內容的 pom.xml 檔案:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.6</version>
</dependency>
</dependencies>
</project>
此檔案是可設定要使用之專案的 Apache Maven 檔案:
- Java 8
- 適用於 Java 的最新 PostgreSQL 驅動程式
準備一個設定檔以連接 Azure HorizonDB
建立 一個 src/main/resources/application.properties 檔案,並新增以下內容:
cat << EOF > src/main/resources/application.properties
url=jdbc:postgresql://${AZ_HORIZONDB_FQDN}:5432/${AZ_DATABASE_NAME}?sslmode=require
user=${AZ_POSTGRESQL_NON_ADMIN_USERNAME}
password=${AZ_POSTGRESQL_NON_ADMIN_PASSWORD}
EOF
Note
配置內容 url 包括 ?sslmode=require 確保 JDBC 驅動程式在連接至資料庫時使用 TLS (傳輸層安全性)。 Azure HorizonDB 需要 TLS,這是推薦的安全實務。
建立 SQL 檔案以產生資料庫架構
使用 src/main/resources/schema.sql 檔案來建立資料庫結構。 建立該檔案,內容如下:
DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description text, details text, done BOOLEAN);
撰寫應用程式程序代碼
連結至資料庫
接著,加入使用 JDBC 來儲存和取回 Azure HorizonDB 實例資料的 Java 程式碼。
建立 src/main/java/DemoApplication.java 檔案,並新增下列內容:
package com.example.demo;
import java.sql.*;
import java.util.*;
import java.util.logging.Logger;
public class DemoApplication {
private static final Logger log;
static {
System.setProperty("java.util.logging.SimpleFormatter.format", "[%4$-7s] %5$s %n");
log =Logger.getLogger(DemoApplication.class.getName());
}
public static void main(String[] args) throws Exception {
log.info("Loading application properties");
Properties properties = new Properties();
properties.load(DemoApplication.class.getClassLoader().getResourceAsStream("application.properties"));
log.info("Connecting to the database");
Connection connection = DriverManager.getConnection(properties.getProperty("url"), properties);
log.info("Database connection test: " + connection.getCatalog());
log.info("Create database schema");
Scanner scanner = new Scanner(DemoApplication.class.getClassLoader().getResourceAsStream("schema.sql"));
Statement statement = connection.createStatement();
while (scanner.hasNextLine()) {
statement.execute(scanner.nextLine());
}
/*
Todo todo = new Todo(1L, "configuration", "congratulations, you have set up JDBC correctly!", true);
insertData(todo, connection);
todo = readData(connection);
todo.setDetails("congratulations, you have updated data!");
updateData(todo, connection);
deleteData(todo, connection);
*/
log.info("Closing database connection");
connection.close();
}
}
這Java程式碼使用 application.properties 以及我們之前建立的 schema.sql 檔案,連接 Azure HorizonDB 實例並建立儲存資料的結構。
在這個檔案中,你可以看到我們註解了插入、讀取、更新和刪除資料的方法:我們會在本文後面寫這些方法,你也可以依序取消註解。
Note
資料庫認證儲存在 application.properties 檔案的使用者和密碼屬性中。 執行 DriverManager.getConnection(properties.getProperty("url"), properties); 時會使用這些認證,因為屬性檔案會作為引數傳遞。
您現在可以使用慣用的工具來執行此主要類別:
- 使用 IDE 時,您應該能夠以滑鼠右鍵按一下 DemoApplication 類別,然後加以執行。
- 使用 Maven 時,您可以藉由執行
mvn exec:java -Dexec.mainClass="com.example.demo.DemoApplication"來執行應用程式。
應用程式應該連接到 Azure HorizonDB 實例,建立資料庫結構,然後關閉連線,如你在主控台日誌中看到的:
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Closing database connection
建立網域類
在 Todo 類別旁建立新的 DemoApplication Java 類別,並新增下列程式碼:
package com.example.demo;
public class Todo {
private Long id;
private String description;
private String details;
private boolean done;
public Todo() {
}
public Todo(Long id, String description, String details, boolean done) {
this.id = id;
this.description = description;
this.details = details;
this.done = done;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
public boolean isDone() {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
@Override
public String toString() {
return "Todo{" +
"id=" + id +
", description='" + description + '\'' +
", details='" + details + '\'' +
", done=" + done +
'}';
}
}
這個類別是在您執行 schema.sqltodo 指令碼時建立的 資料表中對應的領域模型。
將資料插入 Azure HorizonDB
在 src/main/java/DemoApplication.jav 檔案中,在 main 方法後面新增下列方法,以將資料插入資料庫:
private static void insertData(Todo todo, Connection connection) throws SQLException {
log.info("Insert data");
PreparedStatement insertStatement = connection
.prepareStatement("INSERT INTO todo (id, description, details, done) VALUES (?, ?, ?, ?);");
insertStatement.setLong(1, todo.getId());
insertStatement.setString(2, todo.getDescription());
insertStatement.setString(3, todo.getDetails());
insertStatement.setBoolean(4, todo.isDone());
insertStatement.executeUpdate();
}
您現在可以取消 main 方法中下列兩行的註解:
Todo todo = new Todo(1L, "configuration", "congratulations, you have set up JDBC correctly!", true);
insertData(todo, connection);
執行主要類別現在應該會產生下列輸出:
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Insert data
[INFO ] Closing database connection
從 Azure HorizonDB 讀取資料
我們來讀取先前插入的資料,以驗證程式碼是否正常運作。
在 src/main/java/DemoApplication.java 檔案中,於 insertData 方法之後新增以下方法,用於從資料庫讀取資料:
private static Todo readData(Connection connection) throws SQLException {
log.info("Read data");
PreparedStatement readStatement = connection.prepareStatement("SELECT * FROM todo;");
ResultSet resultSet = readStatement.executeQuery();
if (!resultSet.next()) {
log.info("There is no data in the database!");
return null;
}
Todo todo = new Todo();
todo.setId(resultSet.getLong("id"));
todo.setDescription(resultSet.getString("description"));
todo.setDetails(resultSet.getString("details"));
todo.setDone(resultSet.getBoolean("done"));
log.info("Data read from the database: " + todo.toString());
return todo;
}
您現在可以取消 main 方法中下列行的註解:
todo = readData(connection);
執行主要類別現在應該會產生下列輸出:
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Insert data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have set up JDBC correctly!', done=true}
[INFO ] Closing database connection
更新 Azure HorizonDB 中的資料
我們來更新先前插入的資料。
仍然在 src/main/java/DemoApplication.java 檔案中,於 readData 方法之後新增以下方法,用於更新資料庫內的資料:
private static void updateData(Todo todo, Connection connection) throws SQLException {
log.info("Update data");
PreparedStatement updateStatement = connection
.prepareStatement("UPDATE todo SET description = ?, details = ?, done = ? WHERE id = ?;");
updateStatement.setString(1, todo.getDescription());
updateStatement.setString(2, todo.getDetails());
updateStatement.setBoolean(3, todo.isDone());
updateStatement.setLong(4, todo.getId());
updateStatement.executeUpdate();
readData(connection);
}
您現在可以取消 main 方法中下列兩行的註解:
todo.setDetails("congratulations, you have updated data!");
updateData(todo, connection);
執行主要類別現在應該會產生下列輸出:
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Insert data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have set up JDBC correctly!', done=true}
[INFO ] Update data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have updated data!', done=true}
[INFO ] Closing database connection
刪除 Azure HorizonDB 中的資料
最後,我們來刪除先前插入的資料。
仍然在 src/main/java/DemoApplication.java 檔案中,於 updateData 方法之後新增以下方法,用於刪除資料庫內的資料:
private static void deleteData(Todo todo, Connection connection) throws SQLException {
log.info("Delete data");
PreparedStatement deleteStatement = connection.prepareStatement("DELETE FROM todo WHERE id = ?;");
deleteStatement.setLong(1, todo.getId());
deleteStatement.executeUpdate();
readData(connection);
}
您現在可以取消 main 方法中下列行的註解:
deleteData(todo, connection);
執行主要類別現在應該會產生下列輸出:
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Insert data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have set up JDBC correctly!', done=true}
[INFO ] Update data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have updated data!', done=true}
[INFO ] Delete data
[INFO ] Read data
[INFO ] There is no data in the database!
[INFO ] Closing database connection
清理資源
祝賀! 你建立了一個使用 JDBC 來儲存和檢索 Azure HorizonDB 實例資料的 Java 應用程式。
若要清理本快速入門期間使用的所有資源,請使用下列命令刪除資源群組:
az group delete \
--name $AZ_RESOURCE_GROUP \
--yes
相關內容
快速入門:使用 Python 連接並查詢 Azure HorizonDB(預覽版) - 連線至並查詢 Azure HorizonDB(預覽)