此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
初始化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>
前面的示例针对数据库运行两个指定的脚本。第一个
脚本创建一个架构,第二个模板使用测试数据集填充表。脚本
locations 也可以是带有通配符的模式,通常用于资源
在 Spring 中(例如classpath*:/com/foo/**/sql/*-data.sql
).如果您使用
pattern,脚本按其 URL 或文件名的词法顺序运行。
数据库初始值设定项的默认行为是无条件运行提供的 脚本。这可能并不总是您想要的——例如,如果您运行 脚本针对已包含测试数据的数据库。可能性 通过遵循常见模式(如上所示)减少意外删除数据的次数 首先创建表,然后插入数据。如果出现以下情况,第一步将失败 这些表已经存在。
但是,为了更好地控制现有数据的创建和删除,XML 命名空间提供了一些附加选项。第一个是将 初始化打开和关闭。您可以根据环境进行设置(例如将 来自系统属性或环境 Bean 的布尔值)。以下示例从系统属性获取值:
<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
脚本中的语句
因此,会失败。所以失败的 SQLDROP
语句将被忽略,但其他失败
将导致异常。如果您的 SQL 方言不支持DROP … IF
EXISTS
(或类似),但您想在之前无条件删除所有测试数据
重新创建它。在这种情况下,第一个脚本通常是一组DROP
语句
后跟一组CREATE
语句。
这ignore-failures
选项可以设置为NONE
(默认值),DROPS
(忽略失败
drops),或ALL
(忽略所有失败)。
如果字符不是,则每个语句都应用或换行符分隔
完全存在于剧本中。您可以全局控制该作,也可以逐个脚本控制该脚本,如
以下示例显示:;
;
<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
脚本使用 as 语句分隔符,并且仅
这@@
db-schema.sql
使用。此配置指定默认分隔符
is 并覆盖;
@@
db-schema
脚本。
如果您需要比从 XML 命名空间获得的更多的控制,您可以使用DataSourceInitializer
直接将其定义为应用程序中的组件。
初始化依赖于数据库的其他组件
一大类应用程序(那些在 Spring 上下文 started)可以使用数据库初始值设定项,无需进一步 并发症。如果您的应用程序不是其中之一,您可能需要阅读其余部分 本节的。
数据库初始值设定项依赖于DataSource
实例并运行脚本
在其初始化回调中提供(类似于init-method
在 XML Bean 中
定义,一个@PostConstruct
组件中的方法,或afterPropertiesSet()
实现InitializingBean
).如果其他 bean 依赖于
相同的数据源,并在初始化回调中使用该数据源,在那里
可能是个问题,因为数据尚未初始化。一个常见的例子
这是一个缓存,它急切地初始化并在应用程序上从数据库加载数据
启动。
若要解决此问题,您有两个选择:更改缓存初始化策略 到稍后的阶段,或者确保首先初始化数据库初始值设定项。
如果应用程序在您的控制范围内,则更改缓存初始化策略可能很容易,否则则不然。 关于如何实现这一点的一些建议包括:
-
使缓存在首次使用时延迟初始化,从而改善应用程序启动 时间。
-
实现缓存或初始化缓存的单独组件
Lifecycle
或SmartLifecycle
.当应用程序上下文启动时,您可以 自动启动SmartLifecycle
通过设置其autoStartup
标志,你可以 手动启动Lifecycle
通过调用ConfigurableApplicationContext.start()
在封闭上下文上。 -
使用弹簧
ApplicationEvent
或类似的自定义观察者机制来触发 缓存初始化。ContextRefreshedEvent
总是由上下文发布 它已准备好使用(在所有 bean 都初始化之后),因此这通常是一个有用的 钩子(这是SmartLifecycle
默认情况下有效)。
确保首先初始化数据库初始值设定项也很容易。关于如何实现这一点的一些建议包括:
-
依赖 Spring 的默认行为
BeanFactory
,即豆子是 按注册顺序初始化。您可以通过采用通用的 一套<import/>
XML 配置中的元素,将 应用程序模块,并确保数据库和数据库初始化 列在第一位。 -
将
DataSource
以及使用它并控制其 通过将它们分开来排序ApplicationContext
实例(例如, parent 上下文包含DataSource
,子上下文包含业务 组件)。这种结构在 Spring Web 应用程序中很常见,但可以更多 普遍适用。