我正在研究Liquibase,将其作为一种潜在的解决方案,使用预先存在的数据库服务器(不同类型)部署我的web应用程序。
这个应用程序应该使用一个只能操作数据的用户来访问数据库,我想使用另一个用户作为模式所有者。由于我的应用程序使用Spring,我认为我可以使用集成类,尽管这意味着我必须创建第二个数据源,只要我的应用软件运行,它就会一直打开,这就违背了分离帐户的目的。
有人遇到过同样的问题吗?有什么解决方案吗?我当然可以手动执行liquibase并传递相关信息,但我想知道是否有人想出了一种更清洁的方法。
提前感谢您的帮助。
使用Liquibase和Spring Boot(至少2.0+),现在可以在application.yml
:中配置一个单独的Liquibase db用户
spring:
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://...
username: <app_user>
password: ${DB_PASSWORD}
liquibase:
default-schema: my_schema
user: <admin_user>
password: ${DB_ADMIN_PASSWORD}
感谢您的输入Nathan,我研究了Spring和CommandLine类,并最终编写了自己的小型静态方法,该方法使用"所有者"凭据打开DB连接,通过该连接应用变更日志并关闭它。
然后,我从WebApplicationInitializer调用此方法,允许liquibase在初始化Springbean之前运行。通过这种方式,我确信在任何与数据库相关的代码运行之前都会应用这些更改,而且我只能通过数据源进行"用户"连接。
作为一个很好的副作用,在启动单元测试时也可以使用该静态方法,这使我可以在干净创建的数据库上运行测试,而不是依赖hibernate的DDL。
以下是代码示例,第一个是一个实用程序类,它封装了从应用程序的属性文件中检索模式所有者连接详细信息的逻辑(http://pastebin.com/HP4HzFmp),它还有一些方法可以简化与单元测试设置的集成。
然后,在每个web应用程序中,我都使用来自Spring的WebApplicationInitializer,它允许我在应用程序启动时(即Hibernate向DB发出任何请求之前)触发liquibase更改应用程序:http://pastebin.com/anXicM15.这样做可以使我在模式操作和数据相关连接之间保持完全分离。
关于数据库连接细节,我将所有这些细节存储在一个属性文件中,该文件由这段代码直接读取,并由Spring用作Hibernate配置的占位符替换源。如果你想实现进一步的隔离,你可以用一个更安全的位置替换获取连接细节的部件。
您说得对,标准的SpringLiquibase集成只支持传递一个dataSource,并且dataSource将在您的应用程序的整个生命周期中有效。
如果您使用连接池,一旦Liquibase完成连接,它所使用的连接将被关闭,因此不应有活动连接,但您的应用程序中仍会引用该池。
如果您想绕过开放的dataSource,您可能需要创建SpringLiquibase的子类,该子类覆盖afterPropertiesSet()
方法和getDataSouce()
方法。
afterPropertiesSet是运行的主要方法,它创建Liquibase实例,然后运行update方法。如果你的子类创建了一个新的连接,然后调用super.afterPropertiesSet()
,然后关闭连接,你应该能够确保一切都清理干净。在afterPropertiesSet中会调用getDataSource()方法,因此您需要重写该方法以返回在afterPropertiesSet()中创建的连接。
您可以在github.com/…./SpringLiquibase.java 上看到SpringLiquibase是如何实现的