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.
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
Scenario: change the quantity of exactly ONE of 3 order items, then save() the
|
||||
whole aggregate — the idiomatic Spring Data JDBC pattern (see Order#withItems).
|
||||
|
||||
1. UPDATE "JDBC_ORDER" SET "VERSION" = ?, "CUSTOMER_ID" = ? WHERE "JDBC_ORDER"."ID" = ? AND "JDBC_ORDER"."VERSION" = ?
|
||||
2. DELETE FROM "JDBC_ORDER_ITEM" WHERE "JDBC_ORDER_ITEM"."ORDER_ID" = ?
|
||||
3. INSERT INTO "JDBC_ORDER_ITEM" ("ORDER_ID", "ORDER_KEY", "ID", "QUANTITY", "SKU") VALUES (?, ?, ?, ?, ?)
|
||||
4. SELECT "JDBC_ORDER"."ID" AS "ID", "JDBC_ORDER"."VERSION" AS "VERSION", "JDBC_ORDER"."CUSTOMER_ID" AS "CUSTOMER_ID" FROM "JDBC_ORDER" WHERE "JDBC_ORDER"."ID" = ?
|
||||
5. SELECT "JDBC_ORDER_ITEM"."ID" AS "ID", "JDBC_ORDER_ITEM"."SKU" AS "SKU", "JDBC_ORDER_ITEM"."QUANTITY" AS "QUANTITY", "JDBC_ORDER_ITEM"."ORDER_KEY" AS "ORDER_KEY" FROM "JDBC_ORDER_ITEM" WHERE "JDBC_ORDER_ITEM"."ORDER_ID" = ? ORDER BY "ORDER_KEY"
|
||||
|
||||
total statements: 5
|
||||
|
||||
DELETE statements: 1
|
||||
INSERT statements: 1 (but the reload shows 3 rows back: [OrderItem[id=13, sku=SKU-1, quantity=1], OrderItem[id=15, sku=SKU-3, quantity=3], OrderItem[id=14, sku=SKU-2, quantity=999]])
|
||||
|
||||
Spring Data JDBC does not diff the collection: saving an aggregate root with a
|
||||
@MappedCollection deletes every existing child row for that parent and reinserts
|
||||
the current collection from scratch, every time — even when only one of three
|
||||
rows actually changed. What it does NOT do is pay for that with N round trips:
|
||||
the three inserts above are one JDBC *batch* — addBatch() three times,
|
||||
executeBatch() once — so this shows as a single "INSERT" line in the log, not
|
||||
three. This is the real trade the "dropping the ORM" article leads with: you
|
||||
give up field-level dirty checking for the aggregate model, but the replace is
|
||||
a delete plus one batched insert, not delete-plus-N-inserts. For a collection
|
||||
with thousands of rows the row churn is still real (every row is rewritten, not
|
||||
just the changed one); see docs/06-when-this-gets-expensive.md.
|
||||
Reference in New Issue
Block a user