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:
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# Runs FormatMapperProbe under five classpaths and writes output/09-format-mapper-matrix.txt.
|
||||
# Needs PostgreSQL up (scripts/start-databases.sh) and `mvn test-compile` done.
|
||||
set -uo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
OUT=output/09-format-mapper-matrix.txt
|
||||
mkdir -p output target/cp
|
||||
mvn -B -q test-compile >/dev/null 2>&1
|
||||
cp_for() { # name, extra mvn args...
|
||||
local name="$1"; shift
|
||||
mvn -B -q dependency:build-classpath -Dmdep.includeScope=test -Dmdep.outputFile="target/cp/$name.txt" "$@" >/dev/null 2>&1
|
||||
}
|
||||
drop() { tr ':' '\n' < "target/cp/$1.txt" | grep -v -E "$2" | paste -sd: - > "target/cp/$3.txt"; }
|
||||
cp_for j3 # Jackson 3 only: what Spring Boot 4 gives you
|
||||
cp_for j2j3 -Pjackson2 # Jackson 2 and Jackson 3 side by side
|
||||
cp_for j2j3t -Pjackson2,jsr310 # ... plus jackson-datatype-jsr310 for Jackson 2
|
||||
drop j2j3 '/tools/jackson/' j2 # Jackson 2 only
|
||||
drop j2j3t '/tools/jackson/' j2t # Jackson 2 only, with jsr310
|
||||
drop j3 '/tools/jackson/|/com/fasterxml/jackson/' none # no Jackson at all
|
||||
run() { # label, classpath-name, setting
|
||||
local label="$1" cpname="$2" setting="${3:-}"
|
||||
echo "== $label"
|
||||
java -cp "target/test-classes:target/classes:$(cat target/cp/$cpname.txt)" com.ankurm.jsoncolumns.FormatMapperProbe "$setting" 2>&1 \
|
||||
| grep -E '^(setting|on classpath|mapper|stored|read back|FAILED)'
|
||||
echo
|
||||
}
|
||||
{
|
||||
echo "# Hibernate $(grep -o 'hibernate-core-[0-9.A-Za-z]*' target/cp/j3.txt | head -1)"
|
||||
run "A. Jackson 3 only, setting not set" j3
|
||||
run "B. Jackson 2 + Jackson 3, setting not set" j2j3
|
||||
run "C. Jackson 2 only, setting not set" j2
|
||||
run "D. no Jackson at all, setting not set" none
|
||||
run "E. Jackson 2 + Jackson 3, setting = jackson (Jackson 2)" j2j3 jackson
|
||||
run "F. Jackson 3 only, setting = jackson (Jackson 2 absent)" j3 jackson
|
||||
run "G. Jackson 2 + Jackson 3, setting = jackson3" j2j3 jackson3
|
||||
run "H. Jackson 2 + jackson-datatype-jsr310, setting not set" j2t
|
||||
run "I. Jackson 2 + Jackson 3 + jsr310, setting not set" j2j3t
|
||||
} > "$OUT"
|
||||
cat "$OUT"
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Writes output/12-javap-deepcopy.txt: how Hibernate takes the snapshot it later compares with the live JSON attribute.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
mkdir -p output
|
||||
JAR="$(mvn -B -q dependency:build-classpath -Dmdep.outputFile=/dev/stdout 2>/dev/null | tr ':' '\n' | grep 'hibernate-core-')"
|
||||
{
|
||||
echo "# $(basename "$JAR")"
|
||||
echo
|
||||
echo "\$ javap -p -c -cp $(basename "$JAR") org.hibernate.type.descriptor.java.spi.FormatMapperBasedJavaType (deepCopy only)"
|
||||
javap -p -c -cp "$JAR" org.hibernate.type.descriptor.java.spi.FormatMapperBasedJavaType 2>&1 | grep -v '^Picked up' \
|
||||
| sed -n '/ T deepCopy(T);/,/Serializable disassemble/p' | grep -v 'Serializable disassemble'
|
||||
echo
|
||||
echo "\$ javap -p -c -cp $(basename "$JAR") org.hibernate.type.descriptor.java.AbstractJavaType (areEqual only)"
|
||||
javap -p -c -cp "$JAR" org.hibernate.type.descriptor.java.AbstractJavaType 2>&1 | grep -v '^Picked up' \
|
||||
| sed -n '/boolean areEqual(T, T);/,/ireturn/p'
|
||||
} > output/12-javap-deepcopy.txt
|
||||
cat output/12-javap-deepcopy.txt
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# Writes output/13-maven-facts.txt: release dates and metadata read straight from Maven Central (retries on HTTP 429).
|
||||
set -uo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
mkdir -p output
|
||||
M=https://repo1.maven.org/maven2
|
||||
get() { # url -> body (retry on 429/empty)
|
||||
for i in 1 2 3 4 5 6; do
|
||||
body="$(curl -sS --fail "$1" 2>/dev/null)" && [ -n "$body" ] && { printf '%s' "$body"; return 0; }
|
||||
sleep 20
|
||||
done
|
||||
return 1
|
||||
}
|
||||
head_lm() { # url -> Last-Modified
|
||||
for i in 1 2 3 4 5 6; do
|
||||
lm="$(curl -sSI "$1" 2>/dev/null | tr -d '\r' | grep -i '^last-modified:' | cut -d' ' -f2-)" && [ -n "$lm" ] && { echo "$lm"; return 0; }
|
||||
sleep 20
|
||||
done
|
||||
echo "unavailable"
|
||||
}
|
||||
meta() { # label path
|
||||
local x; x="$(get "$M/$2/maven-metadata.xml")" || { echo "$1: metadata unavailable"; return; }
|
||||
echo "$1: release=$(grep -o '<release>[^<]*' <<<"$x" | cut -d'>' -f2) lastUpdated=$(grep -o '<lastUpdated>[^<]*' <<<"$x" | cut -d'>' -f2)"
|
||||
sleep 3
|
||||
}
|
||||
{
|
||||
echo "# Maven Central facts, read $(date -u +%Y-%m-%d)"
|
||||
echo
|
||||
echo "# maven-metadata.xml: <release> and <lastUpdated> (yyyyMMddHHmmss, UTC)"
|
||||
meta "com.vladmihalcea:hibernate-types-60 " com/vladmihalcea/hibernate-types-60
|
||||
meta "com.vladmihalcea:hibernate-types-55 " com/vladmihalcea/hibernate-types-55
|
||||
meta "com.vladmihalcea:hibernate-types-5 " com/vladmihalcea/hibernate-types-5
|
||||
meta "io.hypersistence:hypersistence-utils-hibernate-71" io/hypersistence/hypersistence-utils-hibernate-71
|
||||
meta "io.hypersistence:hypersistence-utils-hibernate-73" io/hypersistence/hypersistence-utils-hibernate-73
|
||||
echo
|
||||
echo "# jar Last-Modified on Central (upload time)"
|
||||
for j in org/hibernate/orm/hibernate-core/7.4.14.Final/hibernate-core-7.4.14.Final.jar \
|
||||
org/springframework/boot/spring-boot/4.1.2/spring-boot-4.1.2.jar \
|
||||
io/hypersistence/hypersistence-utils-hibernate-73/3.16.0/hypersistence-utils-hibernate-73-3.16.0.jar; do
|
||||
echo "$(basename "$j"): $(head_lm "$M/$j")"; sleep 3
|
||||
done
|
||||
echo
|
||||
echo "# hibernate.version that hypersistence-utils-hibernate-73:3.16.0 was built against (its pom)"
|
||||
get "$M/io/hypersistence/hypersistence-utils-hibernate-73/3.16.0/hypersistence-utils-hibernate-73-3.16.0.pom" | grep -E '^\s*<hibernate.version>' | sed 's/^ *//'
|
||||
echo
|
||||
echo "# newest Jackson 3 databind on Central"
|
||||
get "$M/tools/jackson/core/jackson-databind/maven-metadata.xml" | grep -E '<release>' | sed 's/^ *//'
|
||||
} > output/13-maven-facts.txt
|
||||
cat output/13-maven-facts.txt
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# Regenerates every file under output/. Needs JDK 25, Maven 3.9 with access to Maven Central, and the two database servers
|
||||
# from scripts/start-databases.sh (PostgreSQL on 55432, MySQL on 53306; override with PG_URL / MYSQL_URL).
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
mvn -B -q clean >/dev/null
|
||||
./scripts/versions.sh >/dev/null
|
||||
./scripts/maven-facts.sh >/dev/null # release dates read from Maven Central
|
||||
./scripts/javap.sh >/dev/null # deepCopy / areEqual bytecode behind the dirty-checking results
|
||||
mvn -B test # A01-A09, A11: default classpath (Jackson 3 only)
|
||||
mvn -B test -Phypersistence -Dtest='A10*' # hypersistence-utils on a Jackson 3 only classpath
|
||||
mvn -B test -Phypersistence,jackson2 -Dtest='A10*' # ... and with Jackson 2 added
|
||||
./scripts/format-mapper-matrix.sh >/dev/null # nine classpath variants of the FormatMapper probe
|
||||
ls -1 output
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
# Starts the two servers the tests talk to, without Docker. Idempotent. Defaults match Db.java.
|
||||
# PostgreSQL 18.6 : zonky embedded-postgres-binaries-linux-amd64 18.6.0 from Maven Central (initdb, pg_ctl, postgres only), port 55432
|
||||
# MySQL 8.0.x : Ubuntu packages mysql-server-core-8.0 + mysql-client-core-8.0, port 53306
|
||||
# Both refuse to run as root, so this script creates two throwaway OS users (pgj, myj). Run it as root in a disposable sandbox.
|
||||
set -euo pipefail
|
||||
BASE="${BASE:-/tmp/work/dbs}"
|
||||
PGPORT="${PGPORT:-55432}"; MYPORT="${MYPORT:-53306}"
|
||||
mkdir -p "$BASE/pg" "$BASE/mysql"
|
||||
id pgj >/dev/null 2>&1 || useradd -m pgj
|
||||
id myj >/dev/null 2>&1 || useradd -m myj
|
||||
|
||||
if [ ! -x "$BASE/pg/pg/bin/postgres" ]; then
|
||||
curl -sSfL -o "$BASE/pg/pg.jar" \
|
||||
https://repo1.maven.org/maven2/io/zonky/test/postgres/embedded-postgres-binaries-linux-amd64/18.6.0/embedded-postgres-binaries-linux-amd64-18.6.0.jar
|
||||
(cd "$BASE/pg" && unzip -o -q pg.jar && mkdir -p pg && tar -xJf postgres-linux-x86_64.txz -C pg)
|
||||
fi
|
||||
chmod -R a+rX "$BASE/pg"
|
||||
if [ ! -f "$BASE/pg/data/PG_VERSION" ]; then
|
||||
mkdir -p "$BASE/pg/data"; chown pgj "$BASE/pg/data"
|
||||
su pgj -c "cd /tmp && $BASE/pg/pg/bin/initdb -D $BASE/pg/data -U postgres -A trust -E UTF8 >/dev/null"
|
||||
fi
|
||||
su pgj -c "$BASE/pg/pg/bin/pg_ctl -D $BASE/pg/data -o '-p $PGPORT -k /tmp' -l $BASE/pg/data/pg.log -w start" || true
|
||||
|
||||
if ! command -v mysqld >/dev/null; then
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends mysql-server-core-8.0 mysql-client-core-8.0
|
||||
fi
|
||||
if [ ! -d "$BASE/mysql/data/mysql" ]; then
|
||||
mkdir -p "$BASE/mysql/data"; chown -R myj "$BASE/mysql"
|
||||
su myj -c "mysqld --no-defaults --initialize-insecure --datadir=$BASE/mysql/data >/dev/null 2>&1"
|
||||
fi
|
||||
chown -R myj "$BASE/mysql"
|
||||
if ! mysql -h127.0.0.1 -P"$MYPORT" -uroot -e 'select 1' >/dev/null 2>&1; then
|
||||
su myj -c "nohup mysqld --no-defaults --secure-file-priv=NULL --datadir=$BASE/mysql/data --port=$MYPORT \
|
||||
--socket=$BASE/mysql/my.sock --mysqlx=OFF --bind-address=127.0.0.1 --pid-file=$BASE/mysql/my.pid \
|
||||
--log-error=$BASE/mysql/err.log >/dev/null 2>&1 &"
|
||||
for _ in $(seq 1 40); do mysql -h127.0.0.1 -P"$MYPORT" -uroot -e 'select 1' >/dev/null 2>&1 && break; sleep 1; done
|
||||
fi
|
||||
psql -h 127.0.0.1 -p "$PGPORT" -U postgres -Atc 'select version()'
|
||||
mysql -h127.0.0.1 -P"$MYPORT" -uroot -Ne 'select version()'
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Writes output/00-versions.txt: the exact versions this module ran against.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
mkdir -p output
|
||||
{
|
||||
echo "# java -version"
|
||||
java -version 2>&1 | grep -v '^Picked up'
|
||||
echo
|
||||
echo "# resolved libraries (mvn dependency:list, default profile)"
|
||||
mvn -B -q dependency:list -DincludeScope=test -DoutputFile=/dev/stdout 2>/dev/null \
|
||||
| grep -E 'hibernate-core|jackson-(databind|core|annotations)|postgresql:|mysql-connector-j|spring-boot:jar|spring-data-jpa|jakarta.persistence-api' | sed 's/^ *//' | sort
|
||||
echo
|
||||
echo "# PostgreSQL server"
|
||||
psql -h "${PGHOST:-127.0.0.1}" -p "${PGPORT:-55432}" -U postgres -Atc 'select version()'
|
||||
echo
|
||||
echo "# MySQL server"
|
||||
mysql -h127.0.0.1 -P"${MYPORT:-53306}" -uroot -Ne 'select version()'
|
||||
} > output/00-versions.txt
|
||||
cat output/00-versions.txt
|
||||
Reference in New Issue
Block a user