Bootiful Azure:使用 Microsoft SQL Server 进行基于 SQL 的数据访问 (2/6)

工程技术 | Josh Long | 2019年1月7日 | ...

这是向 Spring 开发者介绍 Microsoft Azure 的六部分系列文章中的第 2 部分,每周一和周四发布新帖子。如果没有 Microsoft 的 Asir Vedamuthu Selvasingh、Yitao Dong、Bruno Borges、Brian Benz 和 Theresa Nguyen 的贡献,我不可能完成这项工作。您可以在 Github 上找到本系列的代码。在阅读时,如果您有任何反馈或问题,请在 Twitter (@starbuxman) 上联系我。您还可以在我的 Spring Tips (@SpringTipsLive) 系列文章 Bootiful Azure 中了解更多关于 Microsoft Azure 的信息。

以下是所有系列文章

让我们从一个简短而美好的事物开始,传奇的 Microsoft SQL Server。Microsoft SQL Server 是一个有趣的“野兽”。当然,你可以自己运行它,但难道你不想让构建该产品的 Microsoft 来为你做这件事吗?那*才*是全方位服务解决方案!想象一下这有多棒?你在其他场景中不常见到这种解决方案。想象一下,你买了一辆你可以随心所欲地开得飞快的车,而且制造商保证任何和所有的维护和维修?永远?即使这辆车被一颗小行星撞击?这就是为什么在 Microsoft Azure 上运行 Microsoft SQL Server 如此吸引人:拥有权力的苦差事被消除了。

别误会我的意思。SQL Server 本身有很多值得推荐的地方。SQL Server 自 1989 年就已经存在了!它通常与 Oracle DB 和 PostgreSQL 等数据库一同被列为功能最丰富的数据库选项之一。它经过数十年的构建,旨在服务于企业用例。它甚至拥有其他数据库(包括久负盛名的 PostgreSQL)有时缺乏的功能,例如透明数据加密,其中静态数据被透明地加密。

SQL Server 的起源是一个企业级数据库,它在一个操作系统上运行……OS/2!等等,OS/2?你肯定是指 Microsoft Windows 吧?不!微软在 20 世纪 80 年代后期与 Ashton-Tate 和 Sybase 合作,为 IBM OS/2(当时与微软共同开发)创建了一个 Sybase SQL Server 的变体,并于次年发布。

这是 Microsoft SQL Server 的第一个版本,也是 Microsoft 进入企业级数据库市场的开端,与 Oracle、IBM 以及后来的 Sybase 竞争。SQL Server 6.0 是第一个在没有 Sybase 指导下为 NT 设计的版本。

Windows NT 于 1993 年 7 月发布,Sybase 和 Microsoft 走向了不同的方向。各自追求自己的设计和市场方案。Microsoft 协商了所有为 Microsoft 操作系统编写的 SQL Server 版本的独家权利。今天的 Sybase 和 Microsoft SQL Server 是两个截然不同的东西,代码库也完全不同。现在,Microsoft 为不同的用例和工作负载维护着多个版本的 SQL Server。很难描述 Microsoft SQL Server 为何如此出色,所以我将转而向您介绍这个 非常详尽的维基百科页面,它展示了 不同 SQL 数据库引擎的各种功能。Microsoft SQL Server 表现相当不错!

在 Microsoft Azure 上配置 SQL Server

所以,我原本希望通过截图向您展示如何按照这些说明在用户界面中操作,但这似乎不太理想,因为 Azure 门户中的事物往往……不稳定。它们会移动。而且,这些操作脚本化程度无限低。所以,我们将使用 az CLI。问题是,它有点……乏味。

从逻辑上讲,我们要做的非常简单。我们要

  • 创建一个 SQL Server 服务器实例
  • 在服务器中创建一个 SQL Server 数据库。我们的 Spring Boot 应用程序将使用样本模式和数据预加载它。
  • 将 SQL Server 实例暴露给来自我们计算机的客户端访问

我们将使用脚本来完成这项工作

#!/bin/bash

# Set an admin login and password for your database
export adminlogin=bootiful
export password=B00t1ful

# The logical server name has to be unique in the system
export servername=${1}-server

# The ip address range that you want to allow to access your DB
export startip=0.0.0.0
export endip=223.255.255.255

# the name of the resource group
export rg=$1

# Create a logical server in the resource group
az sql server create \
    --name $servername \
    --resource-group $rg \
    --admin-user $adminlogin \
    --admin-password $password

# Configure a firewall rule for the server
az sql server firewall-rule create \
    --resource-group $rg \
    --server $servername \
    -n AllowYourIp \
    --start-ip-address $startip \
    --end-ip-address $endip

# Create a database in the server with zone redundancy as true
az sql db create \
    --resource-group $rg \
    --server $servername \
    --name ${1}-sample-db \
    --service-objective Basic

这将输出一*大堆* JSON!天哪!我从 Azure 文档中提取了这个例子,谢天谢地!我不想自己来想出这个解决方案。您需要注意控制台打印出的第一个 JSON 段落中的 name 属性。我们使用 $RANDOM 变量生成了一个,嗯,随机名称,所以它在您的机器上会不同。在我的机器上,值是 bootiful-22952

现在,您有了一个工作的服务器和服务器内的一个工作的数据库。如果您在 Azure Portal 中四处查看,您将获得连接到数据库所需的所有连接信息。或者,您可以使用这个一个简单的小技巧

az sql db show-connection-string --client jdbc --name bootiful-sample-db

此命令为您提供多种技术的客户端连接字符串,包括 Windows ADO 子系统、Java 的 JDBC 驱动接口和 PHP 的 PDO 接口。您需要将 URI 中的 <server><username><password> 部分替换为适当的值,在本例中分别为 bootiful-serverbootifulB00t1ful。或者,正如我们稍后将看到的,您可以定义属性并使用属性占位符解析来参数化连接字符串的这一部分。

将 SQL Server 引入您的 Spring 应用程序

既然我们已经有了一个全新配置并正常运行的 SQL Server 实例,我们只需像在代码中使用任何其他 JDBC 依赖项一样使用它即可。如果您使用 Spring Initialzir,您可以选择 SQL Server,相应的依赖项将被添加到您的 Maven 或 Gradle 构建中。或者,您可以使用以下坐标手动将其添加到您的构建中:com.microsoft.sqlserver : mssql-jdbc。您无需指定版本;Spring Boot 本身会为您完成此操作。这个特定的依赖项以及与 Microsoft 技术的集成甚至不需要特定的 Maven bill-of-materials 依赖项 - 它就能正常工作。

然后,您需要指定常用的配置属性,以便 Spring 可以为您实例化到 DataSource 的连接。


sql-db=bootiful-sample-db
sql-username=bootiful
sql-password=B00t1ful
sql-servername=bootiful-server

spring.datasource.url=jdbc:sqlserver://${sql-servername}.database.windows.net:1433;database=${sql-db};user=${sql-username}@${sql-servername};password=${sql-password};encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30
spring.datasource.username=${sql-username}
spring.datasource.password=${sql-password}

spring.datasource.initialization-mode=always

我已将用户名和密码编码在此属性文件中。这是一个**糟糕**的主意。通常,您会希望这类信息存储在环境变量或像 Spring Cloud Config Server 这样的配置服务中。撇开这些设置不谈,使用所得的连接与任何支持 JDBC(通常)和 Microsoft SQL Server(特别是)的技术都非常简单。

我们的应用程序将使用需要事先安装在数据库中的数据。Spring 可以帮助我们解决这个问题。如果您在属性文件中指定 spring.datasource.initialization-mode=always,Spring Boot 可以自动对配置的 DataSource 执行 src/main/resources/schema.sqlsrc/main/resources/data.sqlschema.sql 是放置数据库 DDL 的理想位置,而 data.sql 是放置样本数据的理想位置。

出于,嗯,安全原因,我们的 Spring 博客软件不允许我在本文中包含 SQL DDL?所以,这里是 Github 上的 src/main/resources/schema.sql 文件。请查阅。

这是我们的 src/main/resources/data.sql

insert into customer(first_name, last_name)
values ('james', 'watters'),
       ('bob', 'lee'),
       ('trisha', 'gee'),
       ('mario', 'gray'),
       ('spencer', 'gibb'),
       ('yitao', 'dong');

两者都将在我们的各种事件监听器之前执行。让我们看看一个使用 JdbcTemplate 提取这些数据的事件监听器。

package com.example.bootifulazure;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@Log4j2
class SqlServerDemo {

        private final JdbcTemplate jdbcTemplate;

        SqlServerDemo(JdbcTemplate jdbcTemplate) {
                this.jdbcTemplate = jdbcTemplate;
        }

        @EventListener(ApplicationReadyEvent.class)
        public void demo() {
                String query = " select TOP 3 * from customer ";
                RowMapper<Customer> rowMapper =
                    (rs, rowNum) -> new Customer(rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name"));
                List<Customer> customerList = this.jdbcTemplate.query(query, rowMapper);
                customerList.forEach(log::info);
        }

        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        private static class Customer {
                private Long id;
                private String firstName, lastName;
        }
}

SQL Server 对于许多用例来说是一个引人注目的数据库,而 Microsoft Azure 使其易于扩展的事实对每个人都是一个胜利。值得一提的是,R2DBC(一种响应式 SQL 数据存储访问的努力)已经提供了 Microsoft SQL Server 的实现,此外还有 H2 和 PostgreSQL。您甚至可以进行响应式 SQL Server 访问以获得更快的应用程序。所有这些似乎都只需按一下按钮(或者至少是一个繁琐的部署脚本)。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

先行一步

VMware 提供培训和认证,为您的进步加速。

了解更多

获得支持

Tanzu Spring 在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将发生的活动

查看 Spring 社区中所有即将发生的活动。

查看全部