Card 05/ 07

ExampleDifficulty: Advanced1 min

Spring Data JDBC Example: Saving an Aggregate End to End

A record, a table name and a one-line repository, and save writes it with no persistence context.

A Spring Data JDBC repository is written for an aggregate root, the one object through which a cluster of related data is loaded and saved, and the root can be as small as a Java record. BookingAggregate is the root here, and BookingJdbcRepository is the one repository it gets; nothing inside it has a repository of its own.

@Table("bookings") names the table the record maps to, and @Id marks the field the database fills in when the row is inserted:

java
@Table("bookings")
record BookingAggregate(@Id Long id, String pickup) {}

interface BookingJdbcRepository extends CrudRepository<BookingAggregate, Long> {}
text
Spring Data JDBC saved aggregate with generated id: 1
count: 1
run in a container: a real Spring Data JDBC repository, working end to end

save() inserted the booking and returned it with the id the database generated, and count() confirms one row. There is no @OneToMany (JPA's mapping for a one-to-many relationship), no lazy stand-in and no persistence context (JPA's record of the entities it is tracking in the current transaction): save() writes the aggregate in full, and findById would read it back the same way, in one round trip each.

So a Spring Data JDBC repository looks like a JPA one from the outside, and behaves in a simpler way: what you call is exactly what runs.