我最近开始在一个项目上使用Liquibase来跟踪Java Enterprise应用程序中的数据库更改。 我必须说我喜欢它的工作方式。 它使我的应用程序(或应用程序的新版本)到另一个环境的部署更加容易,并且(更加)可靠。 过去,我必须向DBA提供一个数据库脚本,该脚本必须在重新部署EAR / WAR文件之后以及此过程附带的所有问题后立即执行(脚本失败/ DBA不可用,等等)。 现在,我不会说这个解决方案不会有问题,但是从开发人员的角度来看,它确实使生活变得更轻松。
这是它对带有某些由MySQL数据库支持的Web服务的纯Maven项目的工作方式。 因为我将Web服务部署在JBoss上的WAR文件中,所以我选择由ServletContextListener实例触发Liquibase脚本。 为了能够测试数据库脚本而不必部署应用程序,我还在pom文件中嵌入了Liquibase的Maven插件。 这样,我可以使用Maven对本地开发数据库手动运行liquibase脚本。
首先将必要的依赖项添加到Maven pom.xml中:
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.15</version>
<scope>provided</scope>
</dependency>
仅需要MySQL依赖关系才能使用Maven运行Liquibase脚本。 在本例中,应用程序本身使用由容器管理的数据源JBoss。 为了能够使用Maven运行Liquibase脚本,我定义了如下插件:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>2.0.1</version>
<configuration>
<changeLogFile>db.changelogs/my-changelog-master.xml</changeLogFile>
<driver>com.mysql.jdbc.Driver</driver>
<url>jdbc:mysql://localhost:3306/MyDB</url>
<username>admin-user</username>
<password>*****</password>
</configuration>
<executions>
<execution>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
就像我说的那样,我通过使用Servlet侦听器触发Liquibase来执行脚本。 要进行设置,请将以下元素添加到WAR文件中的“ web.xml”中:
...
<context-param>
<param-name>liquibase.changelog</param-name>
<param-value>db.changelogs/db.changelog-master.xml</param-value>
</context-param>
<context-param>
<param-name>liquibase.datasource</param-name>
<param-value>java:jboss/datasources/LiquibaseDS</param-value>
</context-param>
<listener>
<listener-class>liquibase.integration.servlet.LiquibaseServletListener</listener-class>
</listener>
...
在这里,我们看到我定义了两个参数:
- liquibase.changelog
此参数引用主db.changelogs文件的类路径位置。 重要的是要注意,如果您在同一数据库上运行,则此路径与Maven插件中使用的路径匹配。 请参阅使用不同路径时遇到的此问题 。
- liquibase.datasource
这是指与Liquibase脚本一起使用的数据源的JNDI名称。 由于此数据库用户需要创建表之类的数据库对象的权限,因此我建议创建一个单独的数据源以与应用程序一起使用。 然后,该数据源应与仅具有访问数据权限且不能创建或删除对象的用户连接。
最后一部分是db.changelogs文件的创建。 作为建议在这里作为最佳实践我指的是在配置的“主” changelog文件。 在此主变更日志文件中,我引用了各个脚本。 例如,我的“资源”文件夹中有以下“主”脚本:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<include file="db.changelog-1.0.xml" relativeToChangelogFile="true" />
<include file="db.changelog-2.0.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
在“ db.changelog-1.0.xml”脚本中,我使用基于XML的变更集创建了一些表:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<changeSet id="1" author="pascalalma">
<createTable tableName="TEST_TABLE">
<column name="ID" type="bigint(20)" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="CODE" type="varchar(20)">
<constraints nullable="false" unique="true"/>
</column>
<column name="DESCRIPTION" type="varchar(200)"/>
<column name="VALUE" type="varchar(200)"/>
</createTable>
<addUniqueConstraint columnNames="CODE,DESCRIPTION"
constraintName="CODE_UK"
tableName="TEST_TABLE"/>
<createTable tableName="ANOTHER_TEST_TABLE">
<column name="ID" type="bigint(20)" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="CODE" type="varchar(20)">
<constraints nullable="false" unique="true"/>
</column>
<column name="TEST_CODE" type="bigint(20)">
</column>
</createTable>
<addForeignKeyConstraint baseColumnNames="TEST_CODE"
baseTableName="ANOTHER_TEST_TABLE"
constraintName="TEST_OTHER_FK"
referencedColumnNames="CODE"
referencedTableName="TEST_TABLE"/>
</changeSet>
</databaseChangeLog>
在此示例脚本中,我演示了如何创建具有唯一约束的列的表,以及如何向它们添加外键。
在“ db.changelog-2.0.xml”中,我演示如何通过使用CSV文件作为输入将数据加载到创建的表中:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<changeSet id="2" author="pascalalma">
<loadData file="db.changelogs/mydata.csv"
schemaName="MyDB"
quotchar="'"
tableName="TEST_TABLE"/>
</changeSet>
</databaseChangeLog>
在“ mydata.csv”中,我定义了要上传到表中的行:
CODE,DESCRIPTION,VALUE
'T01','Not specified','FOO'
'T02','Wrongly specified','BAR'
'T03','Correct','FOO-BAR'
CSV文件的第一行按字段在其他行中定义的顺序列出各列。 这是将初始数据加载到数据库表中的一种非常方便的方法。 完成所有这些操作后,您可以从Maven运行Liquibase。 首先使用“ mvn clean install”构建项目,然后给出“ mvn liquibase:update”:
现在,如果我们查看数据库方案中的结果,我们将看到以下表格:
我们看到正在创建带有数据的表。 我们还将看到另外两个表:“ DATABASECHANGELOG”和“ DATABASECHANGELOGLOCK”。 Liquibase使用这些来确定数据库的状态。 如果我使用该数据库的数据源部署WAR文件,那么Liquibase将看到脚本已经运行并且不会再次执行它们。 如果我删除表,则脚本将像针对新数据库一样执行。 如您所见,这可以简化软件新版本(至少是数据库部分)的部署。
翻译自: https://www.javacodegeeks.com/2013/07/source-control-your-database-with-liquibase.html