Closed DemiusAcademius closed 5 months ago
This is only an example
from main pom.xml
<properties>
<caffeine.version>3.1.8</caffeine.version>
<rider.version>1.42.0</rider.version>
<spring-cloud.version>2023.0.1</spring-cloud.version>
<testcontainers-spring-boot.version>3.1.5</testcontainers-spring-boot.version>
</properties>
from main pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>${caffeine.version}</version>
</dependency>
<dependency>
<groupId>com.playtika.testcontainers</groupId>
<artifactId>testcontainers-spring-boot-bom</artifactId>
<version>${testcontainers-spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.github.database-rider</groupId>
<artifactId>rider-spring</artifactId>
<version>${rider.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
Dependency order:
In each group alphabetic order
Lets concentrate only on campaigns. Event types will be hardcoded
example of migration script
V1__create_campaigns_schema.sql
CREATE TABLE campaigns.campaign (
id UUID,
name TEXT NOT NULL,
interval_start TIMESTAMPTZ NOT NULL,
interval_end TIMESTAMPTZ NOT NULL,
loyalty_event_type_id UUID NOT NULL,
created_at TIMESTAMPTZ NOT NULL,
is_active BOOLEAN NOT NULL,
metainfo JSONB NOT NULL,
CONSTRAINT pk_campaign_id PRIMARY KEY (id)
);
CREATE INDEX idx_campaign_interval_start ON campaigns.campaign(interval_start);
CREATE TABLE campaigns.rule (
id UUID,
campaign_id UUID NOT NULL,
conditions JSONB NOT NULL,
effects JSONB NOT NULL,
CONSTRAINT pk_rule_id PRIMARY KEY (id),
CONSTRAINT fk_rule_campaign_id FOREIGN KEY (campaign_id) REFERENCES campaigns.campaign(id)
);
metainfo, conditions and effects will be stored as jsonb
example of working with jsonb
package md.maib.retail.loyalty.campaign.adapter.persistence;
import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import md.maib.retail.loyalty.campaign.domain.model.common.CampaignId;
import md.maib.retail.loyalty.campaign.domain.model.manage.CampaignMetadataEntity;
import md.maib.retail.loyalty.campaign.domain.model.manage.Metadata;
import org.hibernate.annotations.ColumnTransformer;
import org.springframework.data.domain.Persistable;
import java.util.Map;
import java.util.UUID;
@Entity
@Table(name = "campaign_metadata", schema = "campaigns")
@NoArgsConstructor
@AllArgsConstructor
@Getter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class CampaignMetadataRecord implements Persistable<UUID> {
@Id
@EqualsAndHashCode.Include
@Column(name = "campaign_id", nullable = false)
private UUID id;
@Column(name = "metadata", nullable = false)
@Convert(converter = EntityFieldJsonConverter.class)
@ColumnTransformer(write = "?::jsonb")
private Map<String, Object> metadata;
@Transient
private boolean isNew;
@Override
public boolean isNew() {
return isNew;
}
public static CampaignMetadataRecord of(CampaignMetadataEntity entity) {
return new CampaignMetadataRecord(entity.id().value(), entity.metadata().properties(), true);
}
public CampaignMetadataEntity toEntity() {
return new CampaignMetadataEntity(new CampaignId(this.id), new Metadata(this.metadata));
}
}
Converter jsonb <-> Map
package md.maib.retail.loyalty.campaign.adapter.persistence;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import lombok.SneakyThrows;
import java.util.Map;
@Converter(autoApply = true)
public class EntityFieldJsonConverter implements AttributeConverter<Map<String, Object>, String> {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Override
@SneakyThrows
public String convertToDatabaseColumn(Map<String, Object> attribute) {
return objectMapper.writeValueAsString(attribute);
}
@Override
@SneakyThrows
public Map<String, Object> convertToEntityAttribute(String dbData) {
return objectMapper.readValue(dbData, new TypeReference<>() {
});
}
}
can you show classes md.maib.retail.loyalty.campaign.domain.model.manage.CampaignMetadataEntity; md.maib.retail.loyalty.campaign.domain.model.manage.Metadata;
Materials: https://www.baeldung.com/database-migrations-with-flyway https://flywaydb.org/ https://database-rider.github.io/database-rider/
pom.xm examplel
Caffeine used for cashing Flyway for migrations com.playtika.testcontainers for integration testing with containers Rider also for integration testing