JPA

JPA Storage

Quartz provides robust first-class support for Jakarta Persistence (JPA) through the JPAStorage contract, a specialized interface that exposes entity persistence, query execution, and integration with the Quartz query and specification infrastructure.

Overview

The JPAStorage interface builds on top of Quartz’s SimpleStorage, enhancing it with:

  • Flush control: Manage pending persistence state via flush() and saveAndFlush().
  • Transactional boundaries: Write operations are implicitly wrapped in transactions.
  • Interceptors: Transparent support for transaction handling and cleanup.
  • Full support for JPQL, native SQL, and dynamic query specifications.

At runtime, JPAStorage instances are backed by HibernateJPAStorage, a type-safe storage engine built on top of EntityManager and fully integrated with Quartz’s dependency injection and lifecycle management.

Defining a JPA Storage

To define a JPA-backed repository, simply declare an interface annotated with @Storage and extend JPAStorage:

@Storage
public interface UserStorage extends JPAStorage<UserEntity, UUID> {
  Optional<UserEntity> findByUsername(String username);
}

Quartz automatically binds the interface to HibernateJPAStorage through the JPAStorageProvider, using your application's injected EntityManagerFactory.

Runtime Behavior

The storage is provisioned lazily, scoped to your application context, and powered by a managed EntityManager. Quartz guarantees:

  • Thread safety across plugin boundaries
  • Memory efficiency by avoiding unnecessary allocations
  • Clean transactional demarcation using the interceptor system
  • Contextual entity manager resolution, allowing external management when needed

Storage Lifecycle

Quartz binds the following interceptors to every JPAStorage instance by default:

  • TransactionalInterceptor: Begins and commits/rolls back transactions around write operations.
  • TransactionCleanupInterceptor: Ensures EntityManager is properly closed and detached from thread-local scope.

Integration with Specifications

Every JPAStorage can extend the QuerySpecificationExecutor interface, allowing complex criteria logic to be composed fluently:

@Storage
public interface UserStorage extends JPAStorage<UserEntity, UUID>, QuerySpecificationExecutor<Entity> { }
List<UserEntity> results = userStorage.find((root, query, cb) ->
  cb.equal(root.get("username"), "admin")
);

You can also paginate and sort:

Page<UserEntity> recent = userStorage.find(spec, Pagination.of(1, 20));

Note

Behind the scenes, this delegates to JPA CriteriaBuilder and constructs type-safe dynamic queries, no string parsing, no reflection, full compile-time safety.

Dynamic Query Execution

The storage system is deeply integrated with Quartz’s custom @Query engine, which supports:

  • JPQL-style queries (e.g., from UserEntity u where ...)
  • Native SQL queries
  • Automatic binding of named and positional parameters
  • Projections, joins, DTO mapping, and aggregates
  • Native Method Name-Based Queries & Quartz Query Language (QQL) Support bundled from Quartz Data

Queries are parsed, validated, and executed through the JPAQueryExecutor, which supports pagination, result counting, and exists checks out of the box.

Customization & Extensibility

Quartz keeps everything modular and extensible:

  • You can override the default JPAStorageProvider with your own bean.
  • You can register custom interceptors, enrich metadata, or augment behavior.
  • You can even subclass HibernateJPAStorage to customize its internal logic.

Why it Matters

In typical Minecraft plugin development, using frameworks like Spring Boot is often overkill, classloader conflicts, heavy dependencies, and poor plugin isolation make it unsustainable.

Quartz solves this by providing:

  • Lightweight, container-independent data access
  • Seamless integration with Bukkit/Spigot, BungeeCord, and other platforms
  • Full async compatibility and a clear DI architecture

The JPAStorage system is designed to give you real power with zero boilerplate, while staying 100% compatible with Minecraft's unique runtime environment.


Previous
Specification Executor