Files
sdjpa4-demo/README.md
T
asmhatre 448c383879 Add jdbc-vs-jpa module: Spring Data JDBC vs JPA on a shared Order aggregate
Same Customer/Order/OrderItem domain modelled with Hibernate/Spring Data JPA and
Spring Data JDBC side by side, both running through a shared StatementLoggingDataSource
so SQL-statement counts are directly comparable. 11 tests, 11 captured transcripts,
6 doc chapters. Companion repo for the ankurm.com article on when to drop the ORM.
2026-09-17 19:09:35 +00:00

64 lines
3.7 KiB
Markdown

# sdjpa4-demo
Companion code for the Spring Data JPA and transaction articles on **[ankurm.com](https://ankurm.com)**.
Three independent Maven modules under one aggregator:
| Module | Article(s) | Boot / JDK |
|---|---|---|
| [`migration-behavior/`](migration-behavior) | the four Spring Data JPA 3→4 migration articles | 4.0.6 / 21 |
| [`transactions/`](transactions) | [@Transactional: propagation, isolation and the six silent failures](https://ankurm.com/) | 4.1.1 / 25 |
| [`jdbc-vs-jpa/`](jdbc-vs-jpa) | [Spring Data JDBC vs Spring Data JPA in 2026: When Dropping the ORM Is the Right Call](https://ankurm.com/) | 4.1.1 / 25 |
The modules deliberately pin different Spring Boot versions. `migration-behavior` stays on 4.0.6
because that is what the four published migration articles were written and verified against,
and upgrading it would silently invalidate output those articles quote.
> **Moved in September 2026.** The migration project used to live at the repository root. It is
> now under `migration-behavior/`; source paths gained that prefix and nothing else changed. The
> `article-1-baseline`, `article-2-query-engine` and `article-3-advanced` tags still point at the
> original layout, so a link into a tagged tree is unaffected.
```bash
./mvnw -DskipTests package # all modules
./mvnw test # every test in all three
```
## Tags
- `article-1-baseline`, `article-2-query-engine`, `article-3-advanced` - the exact code each
migration article quotes, frozen at publish time.
- `corner-scenarios` (and `main`) - the enriched, current state described below. Some method
signatures have moved on from the article-tagged snapshots (e.g. `Book`'s `price` is now an
embedded `Money` value object, not a bare `BigDecimal`), so check out the matching article tag
if you want the code to line up exactly with what's quoted in a given post.
## What's covered beyond the three articles (corner-scenario enrichment)
- **Refined Specification API** (`AuthorSpecifications.java`): `PredicateSpecification` reused
across a read and a bulk delete, an explicit `DeleteSpecification` (`CriteriaDelete`-backed),
and an `UpdateSpecification` (`CriteriaUpdate`-backed bulk update composed from an
`UpdateOperation` + a `where(...)` predicate).
- **`JpaSort.unsafe(...)` with a `CASE` expression** - a real
`ORDER BY case when country = 'US' then 0 else 1 end` sort combined with a plain derived query.
- **`Money`, an `@Embeddable` record** value object on `Book.price`, with derived queries that
traverse the embedded path (`findByPriceAmountGreaterThanEqual`, `findByPriceAmount`).
- **A genuine corner case, found by actually running it**: a derived-query class-based (record)
projection resolves constructor-parameter names against *direct* entity properties only.
`BookSummary(String title, BigDecimal amount)` does **not** resolve `amount` against the nested
`price.amount` path via a plain `findBy...` derived method - it throws
`PropertyReferenceException: No property 'amount' found for type 'Book'`. The fix is an
explicit `@Query` constructor expression
(`select new ...BookSummary(b.title, b.price.amount) from Book b where ...`), which does handle
nested/embedded paths. See `BookRepository.findByPriceAmountLessThanEqual`.
All of the above is exercised by both the demo runner (`DemoRunner.java`, sections H-L) and
dedicated tests in `MigrationBehaviorTests.java`.
## jdbc-vs-jpa
Same `Customer`/`Order`/`OrderItem` domain modelled twice - Hibernate/Spring Data JPA and Spring
Data JDBC - against the same H2 database through the same statement-logging `DataSource`, so the
SQL-statement counts quoted in the article are a fair, apples-to-apples comparison. See
[`jdbc-vs-jpa/README.md`](jdbc-vs-jpa/README.md).