I have a confession – I used to hate ORM upgrades. They usually break something obscure in a criteria query I wrote four years ago. I spent most of last Saturday dreading the bump to the new February Hibernate milestones for a legacy Spring Boot service. But we needed the new JSON mapping features bad enough to risk it.

The migration to Hibernate ORM 6.6.0.Alpha1 was surprisingly boring. I mean that as a compliment. I tested this on my M3 Pro Mac with 36GB RAM running PostgreSQL 16.2. The big draw for me was the native JSON handling improvements. In older versions, doing complex JSONB queries in Postgres required native queries or weird custom dialects. But now it just works natively.

Java programming code on screen - Software developer java programming html web code. abstract ...
Java programming code on screen – Software developer java programming html web code. abstract …
@Entity
public class UserProfile {
    @Id
    private Long id;

    @JdbcTypeCode(SqlTypes.JSON)
    private Map<String, String> preferences;
}

You can just write SELECT u FROM UserProfile u WHERE u.preferences['theme'] = 'dark' directly in HQL. And the SQL translation is spot on.

There is a catch though. If you try to map a deeply nested JSON array directly into a Java List<CustomObject> using this milestone, it chokes silently if the JSON has null elements. It won’t throw a mapping exception — it just returns an empty list. I wasted two hours figuring that out. You have to write a custom deserializer if your database has dirty JSON records.

The real reason I am writing this is the Hibernate Search 7.1 milestone. Vector search is everywhere now. I was skeptical about doing it through an ORM instead of just hitting the vector database directly with a dedicated client.

I set up a test with a local pgvector instance. Hooking up the new annotations took maybe five minutes.

@Entity
@Indexed
public class Document {
    @Id
    private Long id;

    @VectorField(dimension = 384)
    private float[] embeddings;
}

I ran a benchmark against 500,000 rows. I expected the ORM translation overhead to ruin the performance. But it didn’t. Querying the top 10 nearest neighbors took about 42ms through the Hibernate Search API. Doing the exact same query via a raw JDBC ORDER BY embeddings <-> ? took 39ms.

A 3ms penalty for type safety and avoiding raw SQL strings is a trade I will make every single time.

I barely touched the Reactive milestone. We have exactly one microservice using Hibernate Reactive with Mutiny. I bumped the version, the test suite passed, and I merged the PR. The Vert.x SQL client dependency tree is still a bit messy if you use Spring Boot 3.4, so watch your exclusions in Gradle. Probably if you don’t exclude the older Netty transitive dependencies, it will fail on startup with a very unhelpful classloader error.

I expected this upgrade to be a massive headache. But instead, I got to delete about 400 lines of custom native queries and replace them with standard HQL. And I am leaving the vector search in our staging environment for another week to watch memory usage under load. If the heap stays stable, it goes to production next Tuesday.

Questions readers ask

How do you query JSONB fields directly in HQL with Hibernate ORM 6.6.0.Alpha1?

Annotate the field with @JdbcTypeCode(SqlTypes.JSON) on a Map or similar type, then write HQL like SELECT u FROM UserProfile u WHERE u.preferences[‘theme’] = ‘dark’. The SQL translation is accurate and removes the need for native queries or custom Postgres dialects that older Hibernate versions required for complex JSONB access. The author deleted roughly 400 lines of native queries after upgrading.

Why does Hibernate 6.6.0.Alpha1 return an empty list when mapping nested JSON arrays?

If the JSON contains null elements inside a deeply nested array being mapped into a Java List, the milestone chokes silently instead of throwing a mapping exception, returning an empty list. The author lost two hours diagnosing this. The workaround is writing a custom deserializer, which is necessary for any database holding dirty or inconsistent JSON records.

How much slower is Hibernate Search 7.1 vector search compared to raw JDBC with pgvector?

Benchmarking against 500,000 rows on a local pgvector instance, a top-10 nearest-neighbor query took about 42ms through the Hibernate Search API versus 39ms using a raw JDBC ORDER BY embeddings <-> ? query. That 3ms overhead buys type safety and avoids raw SQL strings, which the author considered a worthwhile trade for every use case.

Why does Hibernate Reactive fail on startup with Spring Boot 3.4?

The Vert.x SQL client dependency tree conflicts with Spring Boot 3.4, typically because older Netty transitive dependencies are not excluded. This produces a very unhelpful classloader error at startup. The fix is carefully managing Gradle exclusions for the outdated Netty transitives. After handling that, the author’s single Mutiny-based microservice passed its test suite on the Reactive milestone bump.