Liquibase-hibernate changelog generation for entit

2019-02-10 12:00发布

问题:

I am trying to generate diff between Hibernate entities (from a single base package) and a clean database (Oracle 11gR2 XE) through liquibase-maven-plugin using liquibase-hibernate5 (Spring-5.0.4.RELEASE, Hibernate-5.2.15.Final, JPA-2.1.1 application over servlet 3.1 with all (full) programmatic configuration). I am using JSON as change log format and liquibase-hibernate5 (v3.6) with liquibase-maven-plugin (v3.5.5). JPA specification version being used in the config is 2.1.1. Snippet from the POM:

            <plugin>
            <groupId>org.liquibase</groupId>
            <artifactId>liquibase-maven-plugin</artifactId>
            <version>${liquibase.mvn.plugin.version}</version>
            <dependencies>
                <dependency>
                    <groupId>org.liquibase</groupId>
                    <artifactId>liquibase-core</artifactId>
                    <version>${liquibase.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.liquibase.ext</groupId>
                    <artifactId>liquibase-hibernate5</artifactId>
                    <version>${liquibase.hibernate.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-orm</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context-support</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.eclipse.persistence</groupId>
                    <artifactId>javax.persistence</artifactId>
                    <version>${jpa.version}</version>
                </dependency>
                <dependency>
                    <groupId>javax.validation</groupId>
                    <artifactId>validation-api</artifactId>
                    <version>${validation.api.version}</version>
                </dependency>
                <dependency>
                    <groupId>com.oracle.jdbc</groupId>
                    <artifactId>ojdbc8</artifactId>
                    <version>${jdbc.driver.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.yaml</groupId>
                    <artifactId>snakeyaml</artifactId>
                    <version>${snakeyaml.version}</version>
                </dependency>
            </dependencies>
            <configuration>
                <propertyFile>src/main/resources/jdbc/schema/liquibase.properties</propertyFile>
                <propertyFileWillOverride>true</propertyFileWillOverride>
                <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>diff</goal>
                        <goal>update</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

Here is my current liquibase.properties:

url: jdbc:oracle:thin:@localhost:1521/xe
username: db_user
password: password
driver: oracle.jdbc.OracleDriver
referenceUrl: hibernate:spring:org.example.something.entities?dialect=org.hibernate.dialect.Oracle10gDialect
changeLogFile: src/main/resources/jdbc/schema/db-changelog.json
diffChangeLogFile: src/main/resources/jdbc/schema/db-changelog.json

outputDefaultCatalog: false
outputDefaultSchema: false
outputFileEncoding: utf-8

Then in order to run the diff I use as per practice:

mvn liquibase:diff

All seems to work well without errors and an earlier empty changelog file is populated with all applicable changesets; but with one problem that I can't seem to figure out.

Actually, all my entities are grouped and divided across schemas (for segregation, use with microservices, etc. (out of scope for this question). The database user (let's say db_user) I am trying to connect with has all necessary privileges to create tables in all application schemas which will hold data. Let's say schema1 and schema2 being the schemas to which tables for entities below belong:

org.example.something.entities.package1.EntityOne
org.example.something.entities.package2.EntityTwo

Excerpt from entities:

@javax.persistence.Entity
@javax.persistence.Table(schema = "SCHEMA1", name = "TABLE1")
public class EntityOne implements Serializable {
// class code ommitted for brevity

@javax.persistence.Entity
@javax.persistence.Table(schema = "SCHEMA2", name = "TABLE2")
public class EntityTwo implements Serializable {
// class code ommitted for brevity

Now, the problem is that when the changesets get generated they don't have any information about schema names (as assigned by the schema attribute of javax.persistence.Table). This will result in all migrations to be executed in db_user only which is not desirable here. In case of sequences, example code below:

@Id
@Column(name = "id", columnDefinition = "number(18,0)")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "some_id-gen")
@SequenceGenerator(name = "some_id-gen", schema = "SCHEMA1", initialValue = 1001,
    allocationSize = 1, sequenceName = "some_id_seq")
private Long id;

The generated changeset looks like:

{
  "changeSet": {
  "id": "1522402677220-1",
  "author": "os user (generated)",
  "changes": [
    {
      "createSequence": {
        "sequenceName": "SCHEMA1.some_id_seq"
      }
    }]
  }
}

Please note the sequence name, it represents a sequence with name "SCHEMA1.some_id_seq" in db_user and not a sequence with name "some_id_seq" in "SCHEMA1".

What I expect is that these changesets should represent something that tells mvn liquibase:update to run the DDLs in respective schemas. I have tried running the generated changesets and everytime I end up having all objects created in db_user schema (in which I only expect the changelog and changelog lock tables to show up).

I have scoured through StackOverflow and a few other sites but couldn't find anyone with a problem (with solution or tips) similar to mine. Liquibase documentation also doesn't seem to offer much help (may be i can see just the tip of the iceberg); but please, can anyone help here? Or may be point out something very fundamental I missed. :(