Skip to main content
xyz.refineryteam.refinerycore.api.database provides persistent SQL storage backed by HikariCP connection pooling, plus a repository layer that generates dialect-correct SQL for whichever backend you choose — so your plugin’s data-access code doesn’t need to branch on database type.
Looking for data that doesn’t need to survive a restart? See Temporary Storage instead — persistent storage in RefineryCore always means this database layer.

Supported databases

Opening a database

RefineryDatabase has one static factory method per supported type:
PluginDatabase.java
File-based databases (sqlite, h2) resolve their file relative to the plugin’s data folder and create parent directories automatically. Networked databases (mysql, mariadb, postgresql) are pre-tuned with reasonable pool sizing, timeouts, and prepared-statement caching. Always close the database on plugin disable:
Plugin.java

The repository pattern

Rather than writing raw SQL per-entity, extend AbstractRepository<T, ID> and describe your entity’s shape — table creation, upserts, and lookups are generated for you in a dialect-correct way.

Defining an entity and repository

PlayerRepository.java
Four methods to implement:

Registering repositories

RepositoryRegistry tracks repositories against a database, creating each one’s table on registration:
Plugin.java
register() returns the same instance you passed in, so you can assign it directly for convenient access elsewhere in your plugin. Call registry.close() (which closes the underlying database) from onDisable().

Using a repository

Every Repository<T, ID> exposes standard CRUD, each with a blocking and an async (CompletableFuture-based) variant:
PlayerManager.java
save() is always an upsert — insert if the primary key doesn’t exist, update if it does — using each dialect’s native syntax (ON DUPLICATE KEY UPDATE for MySQL/MariaDB/H2, ON CONFLICT ... DO UPDATE for SQLite/PostgreSQL) so you never need to check existence yourself before saving. AbstractRepository also exposes findPage(limit, offset) for pagination without hand-writing LIMIT/OFFSET, and a protected withConnection(ConnectionAction) escape hatch for custom queries (joins across repositories sharing a database, complex WHERE clauses) that the standard CRUD surface doesn’t cover.

Dialect handling — SqlDialect

SqlDialect (xyz.refineryteam.refinerycore.api.database.dialect) encapsulates the small syntax differences between backends that AbstractRepository needs to generate correct SQL: You generally don’t need to touch SqlDialect directly — AbstractRepository resolves it automatically from the RefineryDatabase’s DatabaseType via SqlDialect.of(type). It’s useful to know it exists if you’re writing custom SQL via withConnection and want dialect-correct quoting/upserts without duplicating branching logic.

Low-level access

For anything the repository layer doesn’t cover, RefineryDatabase still exposes raw SQL helpers:
PlayerManager.java
db.getConnection() returns a raw java.sql.Connection from the pool for anything even lower-level.

Required dependencies

Add the JDBC driver(s) for whichever database(s) you use:
List them under libraries.addAll(...) in bukkitPluginYaml (rather than shading them) so Paper’s library loader resolves them at runtime: