Add json-columns module: JSON columns in Hibernate 7.4.14 (@JdbcTypeCode(SqlTypes.JSON)), JSONB querying, GIN/expression indexes, dirty checking, Jackson 3 vs 2 on PostgreSQL 18.6 and MySQL 8.0.46
Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_017ic4b6Kg9RWSTJzyz6KP9X
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# json-columns
|
||||
|
||||
Companion module for the ankurm.com article **JSON Columns in Hibernate 7: `@JdbcTypeCode(SqlTypes.JSON)` and Querying JSONB on PostgreSQL**
|
||||
(https://ankurm.com/hibernate-json-column-jdbctypecode-jsonb-postgresql/).
|
||||
Every claim in the article comes from a test or script here; each writes what it observed to `output/`.
|
||||
The tests run against a real PostgreSQL 18 and a real MySQL 8.0 server started without Docker (see Quickstart).
|
||||
|
||||
## Versions
|
||||
|
||||
| Component | Version | Notes |
|
||||
|---|---|---|
|
||||
| Hibernate ORM | `7.4.14.Final` | newest 7.x GA on Maven Central on 2026-10-30; overrides the `7.4.13.Final` Spring Boot 4.1.2 manages |
|
||||
| Spring Boot | `4.1.2` | parent POM; Spring Data JPA `4.1.2` |
|
||||
| Jackson | `3.1.7` (`tools.jackson`) | what Boot 4.1.2 manages; Jackson 2 `2.22.4` only in the `jackson2` profile |
|
||||
| PostgreSQL / driver | `18.6` / `42.7.14` | `embedded-postgres-binaries-linux-amd64` 18.6.0 from Maven Central, no Docker |
|
||||
| MySQL / driver | `8.0.46` / Connector/J `9.7.0` | Ubuntu 24.04 `mysql-server-core-8.0` package |
|
||||
| hypersistence-utils | `hypersistence-utils-hibernate-73` `3.16.0` | `hypersistence` profile only (A10) |
|
||||
| Java | `25` (Temurin 25.0.5+8) | |
|
||||
|
||||
## Quickstart
|
||||
|
||||
```bash
|
||||
./scripts/start-databases.sh # PostgreSQL on 55432 and MySQL on 53306 (needs root: both servers refuse to run as root, so it makes two OS users)
|
||||
./scripts/run-all.sh # versions + mvn clean test + hypersistence runs + FormatMapper matrix; regenerates everything in output/
|
||||
```
|
||||
|
||||
Point the tests at other servers with `PG_URL`, `PG_USER`, `MYSQL_URL`, `MYSQL_USER` (defaults in `src/test/java/com/ankurm/jsoncolumns/Db.java`).
|
||||
Timings in `output/07-indexing-explain.txt` drift between runs; plan shapes and row counts are asserted.
|
||||
|
||||
## Layout
|
||||
|
||||
| Path | What |
|
||||
|---|---|
|
||||
| `src/main/java/.../model` | `Product` (Map, List, record, POJO columns), `Dimensions` (record), `Specs` (POJO with `equals()`), `Event` (indexing table), `ProductRepository`, `SharedMapperConfig`, `JsonColumnsApplication` |
|
||||
| `src/test/java/.../A01..A11` | one test class per output file (A10 lives in `src/hypersistence-test`, active with `-Phypersistence`) |
|
||||
| `src/test/java/.../Db.java`, `SqlLog.java`, `Transcript.java`, `HqlRunner.java`, `Seed.java` | plain-Hibernate bootstrap, SQL capture, transcript writer, shared HQL case runner, shared sample rows |
|
||||
| `src/test/java/.../FormatMapperProbe.java` | `main()` run by `scripts/format-mapper-matrix.sh` under nine classpaths |
|
||||
| `scripts/` | `start-databases.sh`, `run-all.sh`, `versions.sh`, `format-mapper-matrix.sh`, `javap.sh`, `maven-facts.sh` |
|
||||
|
||||
## Output
|
||||
|
||||
| File | What it shows |
|
||||
|---|---|
|
||||
| `00-versions.txt` | JDK, resolved library versions, PostgreSQL and MySQL server versions |
|
||||
| `01-ddl-postgresql.txt` | the `CREATE TABLE` Hibernate emits for six JSON mappings (json vs jsonb), `json` vs `jsonb` storage differences |
|
||||
| `02-mapping-roundtrip.txt` | Map / List / record / POJO round trip: INSERT, stored JSON, Java types that come back, null vs empty |
|
||||
| `03-dirty-checking.txt` | in-place mutations detected or not, spurious UPDATEs (no `equals()`, `BigDecimal`), `@DynamicUpdate` |
|
||||
| `04-hql-json-functions-postgresql.txt` | every Hibernate 7.4 HQL JSON function run on PostgreSQL 18: generated SQL and result |
|
||||
| `05-embeddable-json-postgresql.txt` | `@Embeddable` stored as JSON, navigated in HQL without `json_value()` |
|
||||
| `06-native-jsonb-operators.txt` | `->>`, `@>`, `?`, `@?`, `@@` in native queries and what Hibernate's parameter parser does to them |
|
||||
| `07-indexing-explain.txt` | 50,000 rows, `EXPLAIN (ANALYZE)` before and after GIN, `jsonb_path_ops` and expression indexes |
|
||||
| `08-mysql.txt` | DDL, round trip, dirty checking, HQL functions, native functions and indexes on MySQL 8.0 |
|
||||
| `09-format-mapper-matrix.txt` | which `FormatMapper` Hibernate picks under nine classpath / setting combinations |
|
||||
| `09-format-mapper-inprocess.txt` | schema evolution failures, `@JsonIgnoreProperties`, a custom `JsonMapper`, `java.time` inside a Map |
|
||||
| `10-hypersistence-*.txt` | `@TypeDef` is gone; hypersistence-utils `JsonType` on Hibernate 7.4.14 with and without Jackson 2 |
|
||||
| `11-spring-boot.txt` | Spring Data repositories with native and HQL JSON queries; Boot's `JsonMapper` is not Hibernate's |
|
||||
| `12-javap-deepcopy.txt` | `javap` of the JSON snapshot copy (`deepCopy` = serialise then parse) and of `areEqual` (`Objects.equals`) |
|
||||
| `13-maven-facts.txt` | release dates and `maven-metadata.xml` facts read from Maven Central (versions callout, hypersistence-utils vs the old hibernate-types) |
|
||||
|
||||
## Not covered (not run)
|
||||
|
||||
Oracle, SQL Server, DB2, H2 and MariaDB JSON dialects, Hibernate's JSON mapping with `SqlTypes.JSON_ARRAY`, `@Embeddable` aggregates on MySQL beyond a single query,
|
||||
`jsonb_path_ops` plus `@?` path indexing, PostgreSQL `jsonb_ops` write amplification, concurrent-write load, `JsonB` (Yasson) as the format mapper, and Hibernate 8.
|
||||
|
||||
MIT — see [LICENSE](../LICENSE).
|
||||
Reference in New Issue
Block a user