Add persistence layer with Liquibase migration
JPA entity, repository, persistence adapter for events. Liquibase changelog creates the events table with BIGSERIAL ID and UUID tokens. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
package de.fete.adapter.out.persistence;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDate;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
/** JPA entity mapping to the events table. */
|
||||
@Entity
|
||||
@Table(name = "events")
|
||||
public class EventJpaEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "event_token", nullable = false, unique = true)
|
||||
private UUID eventToken;
|
||||
|
||||
@Column(name = "organizer_token", nullable = false, unique = true)
|
||||
private UUID organizerToken;
|
||||
|
||||
@Column(nullable = false, length = 200)
|
||||
private String title;
|
||||
|
||||
@Column(length = 2000)
|
||||
private String description;
|
||||
|
||||
@Column(name = "date_time", nullable = false)
|
||||
private OffsetDateTime dateTime;
|
||||
|
||||
@Column(length = 500)
|
||||
private String location;
|
||||
|
||||
@Column(name = "expiry_date", nullable = false)
|
||||
private LocalDate expiryDate;
|
||||
|
||||
@Column(name = "created_at", nullable = false)
|
||||
private OffsetDateTime createdAt;
|
||||
|
||||
/** Returns the internal database ID. */
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/** Sets the internal database ID. */
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/** Returns the public event token. */
|
||||
public UUID getEventToken() {
|
||||
return eventToken;
|
||||
}
|
||||
|
||||
/** Sets the public event token. */
|
||||
public void setEventToken(UUID eventToken) {
|
||||
this.eventToken = eventToken;
|
||||
}
|
||||
|
||||
/** Returns the secret organizer token. */
|
||||
public UUID getOrganizerToken() {
|
||||
return organizerToken;
|
||||
}
|
||||
|
||||
/** Sets the secret organizer token. */
|
||||
public void setOrganizerToken(UUID organizerToken) {
|
||||
this.organizerToken = organizerToken;
|
||||
}
|
||||
|
||||
/** Returns the event title. */
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/** Sets the event title. */
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/** Returns the event description. */
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/** Sets the event description. */
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/** Returns the event date and time. */
|
||||
public OffsetDateTime getDateTime() {
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
/** Sets the event date and time. */
|
||||
public void setDateTime(OffsetDateTime dateTime) {
|
||||
this.dateTime = dateTime;
|
||||
}
|
||||
|
||||
/** Returns the event location. */
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/** Sets the event location. */
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
/** Returns the expiry date. */
|
||||
public LocalDate getExpiryDate() {
|
||||
return expiryDate;
|
||||
}
|
||||
|
||||
/** Sets the expiry date. */
|
||||
public void setExpiryDate(LocalDate expiryDate) {
|
||||
this.expiryDate = expiryDate;
|
||||
}
|
||||
|
||||
/** Returns the creation timestamp. */
|
||||
public OffsetDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
/** Sets the creation timestamp. */
|
||||
public void setCreatedAt(OffsetDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.fete.adapter.out.persistence;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/** Spring Data JPA repository for event entities. */
|
||||
public interface EventJpaRepository extends JpaRepository<EventJpaEntity, Long> {
|
||||
|
||||
/** Finds an event by its public event token. */
|
||||
Optional<EventJpaEntity> findByEventToken(UUID eventToken);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package de.fete.adapter.out.persistence;
|
||||
|
||||
import de.fete.domain.model.Event;
|
||||
import de.fete.domain.port.out.EventRepository;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/** Persistence adapter implementing the EventRepository outbound port. */
|
||||
@Repository
|
||||
public class EventPersistenceAdapter implements EventRepository {
|
||||
|
||||
private final EventJpaRepository jpaRepository;
|
||||
|
||||
/** Creates a new adapter with the given JPA repository. */
|
||||
public EventPersistenceAdapter(EventJpaRepository jpaRepository) {
|
||||
this.jpaRepository = jpaRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event save(Event event) {
|
||||
EventJpaEntity entity = toEntity(event);
|
||||
EventJpaEntity saved = jpaRepository.save(entity);
|
||||
return toDomain(saved);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Event> findByEventToken(UUID eventToken) {
|
||||
return jpaRepository.findByEventToken(eventToken).map(this::toDomain);
|
||||
}
|
||||
|
||||
private EventJpaEntity toEntity(Event event) {
|
||||
var entity = new EventJpaEntity();
|
||||
entity.setId(event.getId());
|
||||
entity.setEventToken(event.getEventToken());
|
||||
entity.setOrganizerToken(event.getOrganizerToken());
|
||||
entity.setTitle(event.getTitle());
|
||||
entity.setDescription(event.getDescription());
|
||||
entity.setDateTime(event.getDateTime());
|
||||
entity.setLocation(event.getLocation());
|
||||
entity.setExpiryDate(event.getExpiryDate());
|
||||
entity.setCreatedAt(event.getCreatedAt());
|
||||
return entity;
|
||||
}
|
||||
|
||||
private Event toDomain(EventJpaEntity entity) {
|
||||
var event = new Event();
|
||||
event.setId(entity.getId());
|
||||
event.setEventToken(entity.getEventToken());
|
||||
event.setOrganizerToken(entity.getOrganizerToken());
|
||||
event.setTitle(entity.getTitle());
|
||||
event.setDescription(entity.getDescription());
|
||||
event.setDateTime(entity.getDateTime());
|
||||
event.setLocation(entity.getLocation());
|
||||
event.setExpiryDate(entity.getExpiryDate());
|
||||
event.setCreatedAt(entity.getCreatedAt());
|
||||
return event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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-latest.xsd">
|
||||
|
||||
<changeSet id="001-create-events-table" author="fete">
|
||||
<createTable tableName="events">
|
||||
<column name="id" type="bigserial" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="event_token" type="uuid">
|
||||
<constraints nullable="false" unique="true"/>
|
||||
</column>
|
||||
<column name="organizer_token" type="uuid">
|
||||
<constraints nullable="false" unique="true"/>
|
||||
</column>
|
||||
<column name="title" type="varchar(200)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="description" type="varchar(2000)"/>
|
||||
<column name="date_time" type="timestamptz">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="location" type="varchar(500)"/>
|
||||
<column name="expiry_date" type="date">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created_at" type="timestamptz" defaultValueComputed="now()">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
|
||||
<createIndex tableName="events" indexName="idx_events_event_token">
|
||||
<column name="event_token"/>
|
||||
</createIndex>
|
||||
|
||||
<createIndex tableName="events" indexName="idx_events_expiry_date">
|
||||
<column name="expiry_date"/>
|
||||
</createIndex>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -6,5 +6,6 @@
|
||||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
|
||||
|
||||
<include file="db/changelog/000-baseline.xml"/>
|
||||
<include file="db/changelog/001-create-events-table.xml"/>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
||||
Reference in New Issue
Block a user