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.
64 lines
3.7 KiB
Markdown
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).
|