搭配 Azure SQL 資料庫來使用 Java 和 JDBC

本主題示範如何建立使用 Java和 JDBC 以在 Azure SQL 資料庫中儲存和擷取資訊的範例應用程式。

JDBC 是連線到傳統關聯式資料庫的標準 Java API。

必要條件

準備工作環境

我們將使用環境變數來限制輸入錯誤,並讓您更輕鬆地針對特定需求自訂下列設定。

使用下列命令來設定一些環境變數:

AZ_RESOURCE_GROUP=database-workshop
AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
AZ_LOCATION=<YOUR_AZURE_REGION>
AZ_SQL_SERVER_USERNAME=demo
AZ_SQL_SERVER_PASSWORD=<YOUR_AZURE_SQL_PASSWORD>
AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>

用本文中使用的以下值替換預留位置:

  • <YOUR_DATABASE_NAME>:您的 Azure SQL 資料庫伺服器的名稱。 此名稱在 Azure 中必須是唯一。
  • <YOUR_AZURE_REGION>:您將使用的 Azure 區域。 根據預設,您可以使用 eastus,但建議您設定為居住地附近的區域。 可以輸入 az account list-locations 來取得可用區域的完整清單。
  • <AZ_SQL_SERVER_PASSWORD>:Azure SQL 資料庫伺服器的密碼。 該密碼至少要有八個字元。 所用字元必須包含下列類別的其中三種:英文大寫字母、英文小寫字母、數字 (0-9) 和非英數字元 (!、$、#、% 等等)。
  • <YOUR_LOCAL_IP_ADDRESS>:您本機電腦的 IP 位址,您將會從那裡執行 Java 應用程式。 能夠很方便找到它的方式之一是將瀏覽器指向 whatismyip.akamai.com

接下來,使用下列命令建立資源群組:

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION \
    | jq

注意

我們使用 jq 公用程式來顯示 JSON 資料,並使其更易於閱讀。 根據預設,此公用程式安裝在 Azure Cloud Shell 上。 如果不喜歡該公用程式,可以安全地移除我們將使用的所有命令的 | jq 部分。

建立 Azure SQL 資料庫執行個體

我們將建立的第一件事是受控 Azure SQL 資料庫伺服器。

注意

您可以在快速入門:建立 Azure SQL 資料庫單一資料庫中,深入了解如何建立 Azure SQL 資料庫伺服器。

Azure Cloud Shell 中執行下列命令:

az sql server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --location $AZ_LOCATION \
    --admin-user $AZ_SQL_SERVER_USERNAME \
    --admin-password $AZ_SQL_SERVER_PASSWORD \
    | jq

此命令將建立 Azure SQL 資料庫伺服器。

設定 Azure SQL 資料庫伺服器的防火牆規則

Azure SQL 資料庫執行個體預設受到保護。 它們具有不允許任何連入連線的防火牆。 若要使用資料庫,必須新增防火牆規則,以允許本機 IP 位址存取資料庫伺服器。

由於您在本文開頭設定了本機 IP 位址,可以執行下列命令來開啟伺服器的防火牆:

az sql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-local-ip \
    --server $AZ_DATABASE_NAME \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS \
    | jq

設定 Azure SQL 資料庫

您稍早建立的 Azure SQL 資料庫伺服器是空的。 其中沒有任何可以搭配 Java 應用程式使用的資料庫。 執行下列命令來建立名為 demo 的新資料庫:

az sql db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name demo \
    --server $AZ_DATABASE_NAME \
    | jq

建立新的 Java 專案

使用您慣用的 IDE,建立新的 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>17</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <version>12.4.2.jre11</version>
        </dependency>
    </dependencies>
</project>

此檔案是設定我們的專案使用的 Apache Maven

  • Java 17
  • 適用於 Java 的最新 SQL Server 驅動程式

準備設定檔以連線到 Azure SQL 資料庫

建立 src/main/resources/application.properties 檔案,然後新增:

url=jdbc:sqlserver://$AZ_DATABASE_NAME.database.windows.net:1433;database=demo;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;
user=demo@$AZ_DATABASE_NAME
password=$AZ_SQL_SERVER_PASSWORD
  • 將兩個 $AZ_DATABASE_NAME 變數替換為您在本文中開頭設定的值。
  • $AZ_SQL_SERVER_PASSWORD 變數替換為您在本文中開頭設定的值。

建立 SQL 檔案以產生資料庫結構描述

我們將使用 src/main/resources/schema.sql 檔案來建立資料庫結構描述。 使用下列內容建立該檔案:

DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id INT PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BIT);

編碼應用程式

連線至資料庫

接下來,請新增 Java 程式碼,其將會使用 JDBC 在您的 Azure SQL 資料庫中儲存及擷取資料。

建立包含以下內容的 src/main/java/com/example/demo/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.propertiesschema.sql 檔案連線到 SQL Server 資料庫,並建立將儲存我們資料的結構描述。

在此檔案中,您可以可以看到我們註解了插入、讀取、更新和刪除資料的方法:我們將在本文的其餘部分撰寫這些方法的程式碼,而且您將能夠彼此取消註解。

注意

資料庫認證儲存在 application.properties 檔案的使用者密碼屬性中。 執行 DriverManager.getConnection(properties.getProperty("url"), properties); 時會使用這些認證,因為屬性檔案會作為引數傳遞。

您現在可以使用慣用的工具來執行此主要類別:

  • 使用 IDE 時,您應該能夠以滑鼠右鍵按一下 DemoApplication 類別並執行它。
  • 使用 Maven 時,您可以藉由執行 mvn package exec:java -Dexec.mainClass="com.example.demo.DemoApplication" 來執行應用程式。

應用程式應該連線到 Azure SQL 資料庫、建立資料庫結構描述,然後關閉連線,如主控台記錄中所見:

[INFO   ] Loading application properties 
[INFO   ] Connecting to the database 
[INFO   ] Database connection test: demo 
[INFO   ] Create database schema 
[INFO   ] Closing database connection 

建立網域類

DemoApplication 類旁邊建立新的 Todo 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.sql 指令碼時所建立 todo 資料表上的領域模型。

將資料插入 Azure SQL 資料庫

src/main/java/DemoApplication.java 檔案中,於 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);

執行 main 類現在應該會產生下列輸出:

[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 SQL 資料庫讀取資料

我們來讀取先前插入的資料,以驗證程式碼是否正常運作。

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);

執行 main 類現在應該會產生下列輸出:

[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 SQL 資料庫中的資料

我們來更新先前插入的資料。

仍然在 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);

執行 main 類現在應該會產生下列輸出:

[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 SQL 資料庫中的資料

最後,我們來刪除先前插入的資料。

仍然在 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);

執行 main 類現在應該會產生下列輸出:

[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 SQL 資料庫儲存和擷取資料的 Java 應用程式。

若要清理本快速入門期間使用的所有資源,請使用下列命令刪除資源群組:

az group delete \
    --name $AZ_RESOURCE_GROUP \
    --yes

下一步