Persistence Configuration
Persistence#
Polyflow ships the database objects required by the Axon Framework core and
the relational views in the polyflow-liquibase artifact. The artifact
supports H2, MariaDB, PostgreSQL, Oracle, Microsoft SQL Server, and Azure SQL.
Manage these objects through Liquibase; do not generate Polyflow DDL through
Hibernate or Maven.
Add the Liquibase artifact alongside the Polyflow modules used by your application:
<dependency>
<groupId>io.holunda.polyflow</groupId>
<artifactId>polyflow-liquibase</artifactId>
<version>${polyflow.version}</version>
</dependency>
Service-owned master changelog#
Each service that owns a database keeps a master changelog, for example
src/main/resources/db/changelog/db.changelog-master.xml. The service includes
the required Polyflow changelogs from that master alongside its own changesets.
This makes the service master the single Liquibase entry point. It also means
that the service configuration stays the same across topologies: only the
contents of its master changelog change.
<?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-4.1.xsd">
<!-- Producer: engine, aggregate persistence, and event processing. -->
<include file="classpath:db/changelog/polyflow/polyflow-core-changelog.xml"/>
<!-- Consumer: JPA projections and event processing. -->
<!-- <include file="classpath:db/changelog/polyflow/polyflow-view-changelog.xml"/> -->
<!-- Include the application's own changelogs here. -->
</databaseChangeLog>
There are two deployment changelogs:
polyflow-core-changelog.xmlis for the producer side: the engine, aggregate event and snapshot storage (DOMAIN_EVENT_ENTRYandSNAPSHOT_EVENT_ENTRY), and event-processing storage (TOKEN_ENTRYandDEAD_LETTER_ENTRY).polyflow-view-changelog.xmlis for the consumer side: JPA view objects and the same event-processing storage. It does not provision aggregate or saga storage.
Service topology configuration#
Choose the includes according to the service's responsibility, not according to the database product:
| Service deployment | Include in the service master changelog |
|---|---|
| Monolith: engine, core, event processing, and JPA views in one service | Core and view masters |
| Producer: engine, core aggregate model, and event processing | Core master |
| Consumer: JPA views and event processing | View master |
| Central platform service that hosts both core and views | Core and view masters |
For a monolith or central platform service, include both:
<include file="classpath:db/changelog/polyflow/polyflow-core-changelog.xml"/>
<include file="classpath:db/changelog/polyflow/polyflow-view-changelog.xml"/>
For separated services, the producer includes only the core master:
<include file="classpath:db/changelog/polyflow/polyflow-core-changelog.xml"/>
The consumer includes only the view master:
<include file="classpath:db/changelog/polyflow/polyflow-view-changelog.xml"/>
The common event-processing changeset has one logical Liquibase path, so
including both masters in one service applies it once. In a separated
deployment, each service applies event-processing storage to its own database.
Saga storage is intentionally not part of either deployment master; the
vendor-specific axonframework-4-saga.sql baseline remains available for
services that explicitly need it.
Configure the application to run this central master changelog. For Spring Boot, each service uses the same configuration and leaves schema creation to Liquibase:
spring:
liquibase:
change-log: classpath:db/changelog/db.changelog-master.xml
jpa:
hibernate:
ddl-auto: validate
Schema changes shipped by a future Polyflow version are applied by upgrading
the polyflow-liquibase dependency and running the same central master
changelog.
If the database already contains Polyflow tables but has no Liquibase history,
adopt the verified existing schema before running updates. Follow
Adopting an existing Polyflow schema
for the one-time changelog-sync and release-tag procedure.
Application adoption mode#
The Liquibase module provides a one-shot Spring Boot adoption mode for deployments that cannot use the Liquibase CLI (see official docs of Liquibse). It is explicitly enabled and uses the application's normal datasource and root changelog:
polyflow:
liquibase:
adoption:
enabled: true
The mode synchronizes the verified existing schema, applies the release tag,
and exits without starting the application. The tag is derived from the
packaged polyflow-liquibase build version: 4.7.1-SNAPSHOT produces tag
4.7. It preserves unrelated application Liquibase history and does not try to
infer whether arbitrary existing tables are equivalent to the Polyflow schema.
Enable it only for the one-time adoption of a schema that an engineer has
already verified.
Release tags#
Each deployment master records its completed Polyflow release with Liquibase's
tagDatabase change. Baseline changeset IDs and tags use the major and minor
version only: 4.6, not 4.6.2. Polyflow follows semantic versioning, so a
persistence-structure change is released in a new minor version; patch
versions do not introduce a new schema version or release tag.
In a monolith, both masters record the same 4.6 tag. In separated
deployments, the producer and consumer databases each record that tag after
their respective baseline has completed.
The Liquibase integration build verifies that this tag matches the major and
minor components of the Maven release version. For example,
4.7.1-SNAPSHOT requires tag 4.7; a mismatch fails the build. Major-version
tag changes are made deliberately as part of the release work.
Schema object naming#
Polyflow assigns explicit names to database objects so that database diagnostics and administration output remain readable across supported database products:
- Primary keys:
PK_<OWNING_TABLE> - Foreign keys:
FK_<OWNING_TABLE>_<REFERENCED_TABLE> - Unique constraints:
UK_<OWNING_TABLE>_<CONSTRAINED_COLUMNS> - Indexes:
IDX_<OWNING_TABLE>_<INDEXED_COLUMNS>
Use concise, unambiguous abbreviations where needed to keep names within Oracle's 30-character identifier limit.
Write schema-object and column names in CAPITAL_CASE. Write SQL keywords and
data types in lowercase, for example create table PLF_TASK (...).
Baseline SQL declares columns and constraints in each create table statement
whenever the referenced object is already available. alter table is reserved
for later schema evolution that cannot be represented during initial object
creation.
View definitions enumerate their selected columns explicitly, including every
branch of a union; they do not use select *.