# blaze-persistence: a Criteria API that reaches for CTEs, keyset pagination and RETURNING

> Blaze-Persistence is a Java library that gives JPA providers a fluent query builder with features the specification leaves out, including common table expressions, recursive CTEs, DML in CTEs, the RETURNING clause and keyset pagination. It is aimed at teams whose queries have outgrown plain Criteria, and it sits on top of Hibernate or EclipseLink rather than replacing them.

**Blazebit/blaze-persistence** — Rich Criteria API for JPA providers

- Repository: https://github.com/Blazebit/blaze-persistence
- Website: https://persistence.blazebit.com
- Stars: 862 · Forks: 108
- Language: Java
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/blazebit-blaze-persistence

## What the library adds on top of the JPA model

Blaze-Persistence describes itself as a rich Criteria API for JPA providers that aims to be better than all the other Criteria APIs available. It provides a fluent API for building queries and removes common restrictions encountered when working with JPA directly. It also works around some JPA provider issues in a transparent way, which is a candid way of saying that the underlying provider still needs those workarounds.

The feature list is where the substance is. The library supports CTEs and recursive CTEs, and modification CTEs, also known as DML in CTEs. It can use the RETURNING clause from DML statements, so a delete or update can hand back the affected rows. The VALUES clause can be used for reporting queries, with table generating functions planned for later. Queries can use set operations such as UNION, EXCEPT and INTERSECT. Entity collections can be managed through DML statements, which is the mechanism for avoiding loading a whole collection into memory when you only need to change it.

Two more additions are about SQL functions rather than SQL structure. You can define functions similar to Hibernate's SQLFunction in a provider agnostic way, and a set of built-in functions is provided, including GROUP_CONCAT, date extraction and date arithmetic. The feature that probably matters most in production is pagination, where the library offers both rich pagination support and keyset pagination.

## Entity views are the second idea in the box

The Entity-View module is described with a memorable analogy: an entity view is to an entity roughly what an RDBMS view is to a table. That framing is more precise than it first appears. An entity is the object graph your persistence model owns, with its relationships, its lazy loading behaviour and its identity. An entity view is a separate, purpose-built shape that selects and projects the fields you actually want for a given use case, and it can be implemented as a separate interface from the entity.

The practical effect is that a read path and a write path stop sharing one class. The upstream documentation covers the entity view module on its own, with its own Javadoc badge, which tells you it is a substantial module rather than a feature flag. The project also ships an entity view archetype, so a running sample is one command away.

This matters most where the same entity serves several audiences. A reporting endpoint, a list view and a write model rarely want the same fields or the same fetch plan. Expressing that difference as a view type rather than as a chain of DTO mappers keeps the projection in one place and lets the query builder fetch what the view declares.

The JPA-Criteria module is the third piece and it takes the opposite direction. It implements the standard Criteria API of JPA but is backed by the Blaze-Persistence Core API, so the objects you get from a CriteriaQuery can be turned into a query builder. That is the bridge for code that is written against the JPA interfaces and cannot be rewritten, such as a third-party library that builds criteria internally.

## Maven coordinates, the BOM and why modules move in lockstep

Blaze-Persistence is split into modules, and the recommendation is to define a version property in your parent pom that you use for all artefacts, because modules are all released in one batch so you can safely increment just that property:

```xml
<properties>
    <blaze-persistence.version>1.6.20</blaze-persistence.version>
</properties>
```

The alternative is the BOM, imported in the dependencyManagement section:

```xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.blazebit</groupId>
            <artifactId>blaze-persistence-bom</artifactId>
            <version>${blaze-persistence.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>    
    </dependencies>
</dependencyManagement>
```

The BOM is the choice worth making. Because the modules are versioned together, importing the BOM removes the class of bug where the entity view module and the core impl drift apart and fail at runtime with a method or type mismatch. The version property approach still works but leaves every module's version to you.

The release history shows a fast cadence. Versions 1.6.18, 1.6.19 and 1.6.20 were published on 2026-02-01, 2026-07-25 and 2026-07-27, and the last push to the repository was on 2026-09-21. The project is not archived, and the CHANGELOG.md and creating-a-release.md files at the top level show a maintained release process rather than an abandoned codebase.

## Archetypes give you a runnable sample in one command

The quickstart section points at Maven archetypes, which is the fastest way to see the library working end to end instead of reading documentation about it. A core only sample is generated with:

```bash
mvn archetype:generate "-DarchetypeGroupId=com.blazebit" "-DarchetypeArtifactId=blaze-persistence-archetype-core-sample" "-DarchetypeVersion=1.6.20"
```

There are variants for each integration path, and the differences between them are the interesting part because they tell you how the library is meant to be wired in. The entity view archetype is `blaze-persistence-archetype-entity-view-sample`, the Spring Data archetype is `blaze-persistence-archetype-spring-data-sample`, the Spring Boot archetype is `blaze-persistence-archetype-spring-boot-sample`, and the DeltaSpike Data archetype is `blaze-persistence-archetype-deltaspike-data-sample`. A Java EE variant exists as `blaze-persistence-archetype-java-ee-sample`.

There are also Jakarta flavoured archetypes for the core only and entity view samples. The pairing tells you that the project maintains both the javax and jakarta namespace variants, which follows from the JPA ecosystem split and from the fact that the examples directory contains both quarkus and quarkus-3 sample projects alongside Spring Data, Spring Data GraphQL, Spring Data SPQR, Spring WebFlux, Spring MVC and Spring HATEOAS examples.

Two integrations are called out in the description of the library itself: with Spring Data or DeltaSpike Data integrations you can make use of Blaze-Persistence in your existing repositories. That is the important claim for adoption, because it means the query builder is reachable from the repository abstraction most Spring applications already use, rather than only from low level EntityManager access.

## Java version requirements are the sharpest edge

The supported runtime section is more complicated than a single minimum version. The projects are built for Java 7 except where dependencies already use Java 8, such as Hibernate 5.2 or Spring Data 2.0, so you are going to need a JDK 8 for building the project. The latest Java version tested and supported is Java 21, and JDK 9 is also supported with an effort to keep up with newer versions.

The wrinkle is what happens when you run on a newer JVM. If you want to run your application on a Java 9 JVM you have to handle the fact that JDK 9 and later no longer export the JAXB and JTA APIs. JDK 11 removed those modules outright, so the command line flags that add modules to the classpath no longer work. Since libraries like Hibernate require those APIs, you have to make them available, and the suggested route is to package them along with your application. The documentation offers the Jakarta XML bind API dependency with a version of 2.3.3, or 3.0.1 if you want Jakarta EE 9, scoped as provided in a managed environment and as compile otherwise.

This is a build and packaging conversation you will have to have once. It is not a defect, but it is the kind of thing that turns into a slow afternoon if you discover it while assembling a container image rather than while reading the documentation.

## Where Blaze-Persistence is the wrong choice

The clearest case against it is a team that has decided to stay inside the JPA specification. Every headline feature in the list, CTEs, RETURNING, set operations, keyset pagination, is an extension that maps onto provider-specific SQL. The library works around provider issues transparently, and transparent workarounds are exactly what a portability strategy is trying to avoid. If your deployment targets several databases with different SQL dialects, the extra SQL surface area becomes a testing burden rather than a saving.

There is also a cost in learning a second query language. The JPA-Criteria module exists precisely because people arrive with existing criteria code, and it exists as a bridge. Teams that adopt the library as their only query layer will find themselves reading provider-specific SQL semantics through a fluent API, and the documentation then becomes a second source of truth next to the SQL documentation of the provider itself.

The comparison with a plain query builder is not really a fair one, and it is worth naming. Spring Data JPA with native queries, or a hand-written repository method backed by a view or a stored procedure, achieves some of the same outcomes with far less machinery. What Blaze-Persistence buys is type safety over the query structure and one consistent builder across reads, bulk DML and projections. If your queries are simple, that is not worth a new layer.

Finally, the licence is Apache-2.0, which is about the easiest commercial answer in the Java ecosystem. There is a LICENSE.txt at the top level of the repository. The constraint here is not legal but technical: a query builder that emits SQL your database does not support will fail at runtime, not at compile time, and that failure mode is what to test before committing to it.

## Conclusion

Blaze-Persistence fits a Java team that has to write reporting and bulk-update queries through JPA and has hit the ceiling of the standard Criteria API, and that is willing to couple its data layer to a third-party query builder. It does not fit a project that wants to stay inside the JPA specification or that cannot accept a JPA provider with SQL dialects underneath. Before adopting it, confirm the Hibernate version your application already uses is compatible with the module you add, pin the release with the BOM, and test the pagination mode on your real data distribution, because offset paging and keyset paging return different rows when the underlying sort is not unique.

## FAQ

### What does Blaze-Persistence add to the standard JPA Criteria API?

It adds CTEs and recursive CTEs, modification CTEs, the RETURNING clause from DML statements, set operations such as UNION, EXCEPT and INTERSECT, the VALUES clause for reporting queries, provider agnostic SQL functions, and both rich and keyset pagination on top of a fluent query builder.

### What is an entity view in Blaze-Persistence?

The Entity-View module creates views for JPA entities. The documentation compares it to a database view over a table, with the view being a separate projection shape rather than the entity itself.

### How do I add Blaze-Persistence to a Maven project?

Define a blaze-persistence.version property in your parent pom and import the com.blazebit blaze-persistence-bom in the dependencyManagement section, or set the version on each module directly. The modules are released in one batch, so a single version property is safe to increment.

### Which Java versions can Blaze-Persistence be built and run with?

You need a JDK 8 to build the project, and Java 21 is the latest version tested and supported, with JDK 9 also supported. On Java 9 and later you have to supply the JAXB and JTA APIs yourself, since JDK 11 removed those modules and the classpath flags no longer work.

### Does Blaze-Persistence work with Spring Data repositories?

Yes. The documentation states that with Spring Data or DeltaSpike Data integrations you can make use of Blaze-Persistence in your existing repositories, and the project ships a Spring Data and a Spring Boot archetype as runnable samples.

## Sources

- [Blazebit/blaze-persistence on GitHub](https://github.com/Blazebit/blaze-persistence)
- [License: Apache-2.0](https://github.com/Blazebit/blaze-persistence/blob/main/LICENSE)
- [Project website](https://persistence.blazebit.com)
- [README](https://github.com/Blazebit/blaze-persistence/blob/main/README.md)
- [Releases](https://github.com/Blazebit/blaze-persistence/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/blazebit-blaze-persistence
