Liquibase bidirectional relationships changelog order

Tags: , , , ,



I’ve faced a problem when implementing liquibase in an existing project. So we have two entities:

Company:

@Entity
@Table(name = "company")
@EqualsAndHashCode(of = {}, callSuper = true)
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Company extends AbstractAccount {

    private String organizationName;
    private String mail;
    private Set<Stock> stocks;
    private Stock currentStock;

    @Column(name = "organization_name", unique = true)
    public String getOrganizationName() {
        return organizationName;
    }

    @Email
    @Column(name = "mail", unique = true)
    public String getMail() {
        return mail;
    }

    @Cascade({CascadeType.REMOVE, CascadeType.SAVE_UPDATE})
    @OneToMany(mappedBy = "company", fetch = FetchType.LAZY)
    public Set<Stock> getStocks() {
        return stocks;
    }

    @OneToOne
    @JoinColumn(name = "current_stock_id", referencedColumnName = "id")
    public Stock getCurrentStock() {
        return currentStock;
    } 
}

Stock:

@Entity
@Table(name = "stock")
@EqualsAndHashCode(of = {}, callSuper = true)
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Stock extends AbstractEntity {

    private String name;
    private Company company;
    private Double fare;

    @Column(name = "panel")
    public Double getFare() {
        return fare;
    }

    @NotBlank(message = "Название акции не может быть пустым.")
    @Column(name = "name")
    public String getName() {
        return name;
    }

    @Cascade({CascadeType.SAVE_UPDATE})
    @ManyToOne(fetch = FetchType.LAZY)
    public Company getCompany() {
        return company;
    }

}

And my liquibase changelogs.

Company:

<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-3.8.xsd">

<changeSet id="1" author="Maxim Grankin">
    <createTable tableName="company">
        <column name="id" type="bigint" autoIncrement="true">
            <constraints primaryKey="true" nullable="false"/>
        </column>
    </createTable>
</changeSet>

<changeSet id="2" author="Maxim Grankin">
    <addColumn tableName="company">
        <column name="organizationName" type="varchar(255)">
            <constraints unique="true"/>
        </column>
        <column name="mail" type="varchar(255)">
            <constraints unique="true"/>
        </column>
        <column name="current_stock_id" type="bigint"/>
    </addColumn>
    <addForeignKeyConstraint baseTableName="company" baseColumnNames="current_stock_id"
                             constraintName="fkoi5aq2bm82091ubh15kfj29m1"
                             referencedTableName="stock"
                             referencedColumnNames="id"/>
</changeSet>

Stock:

<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-3.8.xsd">

<changeSet id="1" author="Maxim Grankin">
    <createTable tableName="stock">
        <column name="id" type="bigint" autoIncrement="true">
            <constraints primaryKey="true" nullable="false"/>
        </column>
    </createTable>
</changeSet>

<changeSet id="2" author="Maxim Grankin">
    <addColumn tableName="stock">
        <column name="name" type="varchar(255)"/>
        <column name="panel" type="double precision"/>
        <column name="company_id" type="bigint"/>
    </addColumn>
    <addForeignKeyConstraint baseTableName="stock" baseColumnNames="company_id"
                             constraintName="fk9r297vk0rghnrccw09x0qybfj"
                             referencedTableName="company"
                             referencedColumnNames="id"/>
</changeSet>

And master:

<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd
    http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">

<include file="data/changelogs/stock/stock/db.changelog.stock.xml"/>
<include file="data/changelogs/company/db.changelog.company.xml"/>

I have this exception:

Caused by: org.postgresql.util.PSQLException: ERROR: relation "public.company" does not exist

I understand that liquibase trying to create stock and then add company_id as foreign key although there is no company table yet. I have a bunch of bidirectional relationships and this one is only part of them.

Question: How can I organize liquibase changeLogs to create all tables and relationships between them in one build? Should I create something like “db.changelogs.relations” where I will set up foreign keys?

UPD: Closed. Generate your changeLogs with maven plugin for liquibase

Answer

Creating Answer out of my Comments on the Question:

It looks you are writing your change log xml manually. If you arrange your change log to put table creation at first and the FKs then it would be fine.

  • Create Table1, Table2, Table3
  • Setup relation between Table1 and Table2, Table2 an Table3

Better option is to use liquibase plugin (for your maven/gradle) to generate such change logs. Liquibase would generate the change logs for tables first and then the FKs so that you don’t need to worry about this.

See these as an reference:



Source: stackoverflow