I've been trying to use liquibase to manage migrations on a Spring JPA project similarly as Python/Django does with makemigrations. Liquibase documentation is extremely confusing, and I've tried to follow a number of SA answers and tutorials I found online but to no avail.
Here's what I'm trying to do:
- Define entities via JPA annotated classes.
- Generate a migration to reflect those entities on a MySQL DB.
- Apply said migration on the database. (Initially empty)
So far I'm able to generate a "diff" changeLog file and somehow managed to get liquibase to create the databasechangelog and databasechangeloglock tables on an empty DB. However, I've not been able to have the master.xml file updated with the diff or have the diff applied on the DB.
Here's my config so far (basic spring-jpa project with just one entity for testing):
Pom.xml (abbreviated)
<project>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>my-group</groupId>
<artifactId>web</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>4.3.2</version>
<configuration>
<changeLogFile>src/main/resources/db/changelog-master.xml</changeLogFile>
<diffChangeLogFile>src/main/resources/db/diff-changelog.xml</diffChangeLogFile>
<outputChangeLogFile>src/main/resources/db/out-changelog.xml</outputChangeLogFile>
<driver>com.mysql.jdbc.Driver</driver>
<referenceUrl>hibernate:spring:my.project.model?dialect=org.hibernate.dialect.MySQL5Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy</referenceUrl>
<url>jdbc:mysql://localhost:3306/my-db?useSSL=false</url>
<username>user</username>
<password>pass</password>
<outputDefaultSchema>true</outputDefaultSchema>
</configuration>
<dependencies>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate5</artifactId>
<version>4.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.27.0-GA</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
application.properties
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=none
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/my-db?useSSL=false
spring.datasource.username = user
spring.datasource.password = pass
spring.liquibase.enabled=true
spring.liquibase.url=jdbc:mysql://localhost:3306/my-db?useSSL=false
spring.liquibase.user=user
spring.liquibase.password=pass
spring.liquibase.change-log=classpath:db/changelog-master.xml
logging.level.org.springframework=INFO
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
hibernate.generate_statistics=true
I also added an empty changelog-master.xml file containing (namespaces excluded):
<databaseChangeLog />
So, if I run spring-boot:run it creates those two databasechangelog tables.(no contents). I can then run mvn liquibase:diff which generates a diff.xml file (albeit with some hibernate warnings). This diff file makes sense to me:
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog>
<changeSet author="tiago (generated)" id="1618352585193-1">
<createTable tableName="chunk">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="chunkPK"/>
</column>
<column name="x_origin" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="y_origin" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
</databaseChangeLog>
But now, how do I apply this? How do I make that diff command "append" this particular diff to the master changelog? Running mvn liquibase:update does nothing. Also, the changelog tables on the DB remain empty.
EDIT: I tried manually adding the diff to the master file like so:
<databaseChangeLog>
<include file="classpath:db/diff-changelog.xml" />
</databaseChangeLog>
After running changelogSync and update I managed to get a record on the databasechangelog table. However the new table was not created.
Thank you for the help,