对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
初始化DataSource
这org.springframework.jdbc.datasource.init
package 支持初始化
现有的DataSource
.嵌入式数据库支持提供了一个用于创建
并初始化DataSource
对于应用程序。但是,有时可能需要初始化
在某处的服务器上运行的实例。
使用 Spring XML 初始化数据库
如果要初始化数据库,并且可以提供对DataSource
bean 中,您可以使用initialize-database
标记中spring-jdbc
Namespace:
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:com/foo/sql/db-schema.sql"/>
<jdbc:script location="classpath:com/foo/sql/db-test-data.sql"/>
</jdbc:initialize-database>
前面的示例对数据库运行两个指定的脚本。第一个
script 创建一个架构,第二个 script 使用测试数据集填充 table。剧本
locations 也可以是带有通配符的模式,采用通常用于资源的 Ant 样式
在 Spring 中(例如,classpath*:/com/foo/**/sql/*-data.sql
).如果您使用
pattern,则脚本将按其 URL 或文件名的词法顺序运行。
数据库初始值设定项的默认行为是无条件地运行提供的 脚本。这可能并不总是您想要的 — 例如,如果您运行 针对已包含测试数据的数据库的脚本。可能性 的意外删除数据通过遵循常见模式来减少(如前所示) 首先创建表,然后插入数据。如果出现以下情况,则第一步失败 表已存在。
但是,为了更好地控制现有数据的创建和删除,XML namespace 提供了一些其他选项。第一个是用于将 initialization on 和 off。你可以根据环境进行设置(比如拉取 boolean 值)。以下示例从 system 属性获取值:
<jdbc:initialize-database data-source="dataSource"
enabled="#{systemProperties.INITIALIZE_DATABASE}"> (1)
<jdbc:script location="..."/>
</jdbc:initialize-database>
1 | 获取 的值enabled 从名为INITIALIZE_DATABASE . |
控制现有数据发生情况的第二个选项是更宽容 失败。为此,您可以控制初始化器忽略某些 错误,如下例所示:
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
<jdbc:script location="..."/>
</jdbc:initialize-database>
在前面的示例中,我们表示我们期望有时运行脚本
针对空数据库,并且有一些DROP
语句
因此,会失败。所以 SQL 失败了DROP
语句将被忽略,但其他失败
将导致异常。如果您的 SQL 方言不支持DROP … IF
EXISTS
(或类似)的 S Lar,但您希望无条件地删除之前的所有测试数据
重新创建它。在这种情况下,第一个脚本通常是一组DROP
语句
后跟一组CREATE
语句。
这ignore-failures
选项可以设置为NONE
(默认值)、DROPS
(忽略失败
drops) 或ALL
(忽略所有失败)。
每个语句都应该用 or 换行符分隔(如果字符不是)
完全存在于脚本中。您可以全局控制它,也可以逐个脚本控制它,因为
以下示例显示:;
;
<jdbc:initialize-database data-source="dataSource" separator="@@"> (1)
<jdbc:script location="classpath:com/myapp/sql/db-schema.sql" separator=";"/> (2)
<jdbc:script location="classpath:com/myapp/sql/db-test-data-1.sql"/>
<jdbc:script location="classpath:com/myapp/sql/db-test-data-2.sql"/>
</jdbc:initialize-database>
1 | 将分隔符脚本设置为 .@@ |
2 | 设置db-schema.sql 自。; |
在此示例中,两个test-data
脚本用作语句分隔符,并且仅
这@@
db-schema.sql
使用。此配置指定默认分隔符
is 并覆盖;
@@
db-schema
脚本。
如果您需要的控制比从 XML 命名空间获得更多的控制权,则可以使用DataSourceInitializer
直接将其定义为应用程序中的一个组件。
初始化依赖于数据库的其他组件
一大类应用程序(那些在 Spring 上下文具有 started) 可以使用数据库初始化器,而无需再使用 并发症。如果您的应用程序不是其中之一,则可能需要阅读其余部分 本节。
数据库初始化器依赖于DataSource
实例并运行脚本
在其初始化回调中提供(类似于init-method
在 XML Bean 中
定义、@PostConstruct
方法,或者afterPropertiesSet()
方法,该组件实现了InitializingBean
).如果其他 bean 依赖于
相同的数据源并在初始化回调中使用数据源,则
可能是个问题,因为数据尚未初始化。一个常见的例子
这是一个 Cache 缓存,它预先初始化并从 Application 上的数据库加载数据
启动。
要解决此问题,您有两个选择:更改缓存初始化策略 添加到稍后的阶段,或者确保先初始化数据库初始值设定项。
如果应用程序由您控制,则更改缓存初始化策略可能很容易。 有关如何实现此功能的一些建议包括:
-
使缓存在首次使用时延迟初始化,从而改善应用程序启动 时间。
-
让您的缓存或初始化缓存的单独组件实现
Lifecycle
或SmartLifecycle
.当应用程序上下文启动时,您可以 自动启动SmartLifecycle
通过设置其autoStartup
标志,您可以 手动启动Lifecycle
通过调用ConfigurableApplicationContext.start()
在封闭的上下文中。 -
使用 Spring
ApplicationEvent
或类似的自定义观察程序机制来触发 cache 初始化。ContextRefreshedEvent
始终由 context 发布,当 它已准备好使用(在所有 bean 都已初始化之后),因此这通常是有用的 hook 的SmartLifecycle
默认有效)。
确保首先初始化数据库初始值设定项也很容易。有关如何实现此功能的一些建议包括:
-
依赖 Spring 的默认行为
BeanFactory
,即 beans 是 按注册顺序初始化。您可以通过采用通用的 一套<import/>
元素,这些元素对 XML 配置中的 应用程序模块,并确保数据库和数据库初始化 列在第一位。 -
将
DataSource
以及使用它并控制其 启动顺序,将它们放在单独的ApplicationContext
实例(例如, parent context 包含DataSource
,子上下文包含业务 组件)。这种结构在 Spring Web 应用程序中很常见,但可能更多 普遍适用。