SQLiteLib
2.0.0This library will make using SQLite super easy! Ditch those YML files, switch to SQLite!
- Tested MC versions
- 1.7, 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.20, 1.21, 26.1, 26.2, 26.3
SQLiteLib
Simple, safe and fast SQLite storage for your plugins. Ditch those YML files!
GitHub | JitPack | Discord | Report a bug
What is SQLiteLib?
Many of you used my tutorial How to: SQLite, and plenty of people found the JDBC code hard to get right. SQLiteLib does all of that for you. Your plugin gets a real database in a few lines, without the boilerplate, connection bugs or SQL injection.
Features
- Parameterized queries: no string building, no SQL injection.
- Typed results: getInt, getUUID, getBoolean, getEnum, or map rows straight to your own objects.
- Async API: every database has its own worker thread, so the main thread never waits on disk.
- Transactions & batch inserts: atomic changes and fast bulk writes.
- Schema migrations: versioned table changes that only run once.
- Key/value stores: a drop-in replacement for data.yml files, with atomic counters.
- Live backups: safe while the server is running.
- Fast defaults: WAL mode, foreign keys, busy timeout.
- Admin commands: inspect, query, back up and vacuum databases in game or from the console.
- Lightweight: no extra downloads. Spigot and Paper already include the SQLite driver.
Requirements
- Java 17+
- Spigot or Paper 1.18+
Commands
Base command: /sqlite (alias /sl)
- /sl list: list loaded databases with size and owner
- /sl info <db>: file, size, schema version, tables and row counts
- /sl query <db> <sql>: run a read-only query and show the rows
- /sl queryvalue <db> <column> <sql>: show a single value
- /sl queryrow <db> <column> <sql>: show one column for every row
- /sl execute <db> <sql>: run any statement
- /sl init <db> [sql]: create/load a database in SQLiteLib's folder
- /sl backup <db>: live backup to plugins/SQLiteLib/backups
- /sl vacuum <db>: compact the database file
Permissions
- sqlite.use: all commands
- sqlite.command.read: list, info, query, queryvalue, queryrow
- sqlite.command.write: execute
- sqlite.command.admin: init, backup, vacuum
All permissions default to op.
Storage
Each plugin's databases are stored in that plugin's own folder (for example plugins/MyPlugin/data.db). Databases created with /sl init are stored in plugins/SQLiteLib. You can open any of them with tools like DB Browser for SQLite.
For developers
Adding the dependency
Add SQLiteLib via JitPack, and add depend: [SQLiteLib] to your plugin.yml.
Maven:
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.pablo67340</groupId>
<artifactId>SQLiteLib</artifactId>
<version>2.0.0</version>
<scope>provided</scope>
</dependency>
Gradle:
repositories { maven("https://jitpack.io") }
dependencies { compileOnly("com.github.pablo67340:SQLiteLib:2.0.0") }
Quick start
private Database db;
@Override
public void onEnable() {
SQLiteLib sqlite = SQLiteLib.hookSQLiteLib();
db = sqlite.open(this, "data"); // plugins/MyPlugin/data.db
db.migrate(
// version 1
"CREATE TABLE homes (owner TEXT NOT NULL, name TEXT NOT NULL, world TEXT NOT NULL, "
+ "x REAL, y REAL, z REAL, PRIMARY KEY (owner, name))",
// version 2 - added in a later update, only runs on servers that don't have it yet
"ALTER TABLE homes ADD COLUMN created INTEGER NOT NULL DEFAULT 0"
);
}
SQLiteLib closes every database cleanly when the server shuts down.
Queries
Always pass values as ? parameters. UUIDs, enums and booleans are converted for you.
db.update("INSERT OR REPLACE INTO homes (owner, name, world, x, y, z) VALUES (?, ?, ?, ?, ?, ?)",
player.getUniqueId(), "base", loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ());
for (Row row : db.query("SELECT * FROM homes WHERE owner = ?", player.getUniqueId())) {
String name = row.getString("name");
double x = row.getDouble("x");
}
Optional<Row> home = db.queryFirst("SELECT * FROM homes WHERE owner = ? AND name = ?", uuid, "base");
long count = db.queryScalar("SELECT COUNT(*) FROM homes WHERE owner = ?", Long.class, uuid).orElse(0L);
Async
db.queryAsync("SELECT name FROM homes WHERE owner = ?", player.getUniqueId())
.thenAcceptAsync(rows -> player.sendMessage("You have " + rows.size() + " homes"),
SQLiteLib.mainThread(this));
Transactions
db.transaction(tx -> {
tx.update("UPDATE balances SET coins = coins - ? WHERE uuid = ?", 100, from);
tx.update("UPDATE balances SET coins = coins + ? WHERE uuid = ?", 100, to);
}); // both happen, or neither does
Key/value stores
KeyValueStore coins = db.keyValue("coins");
String key = player.getUniqueId().toString();
long balance = coins.increment(key, 50); // atomic, returns the new value
coins.set("motd", "Welcome!");
String motd = coins.getString("motd", "");
Backups & maintenance
db.backup(new File(getDataFolder(), "backups/data.db")); // safe while running
db.vacuum();
db.getTables();
db.columnExists("homes", "created");
The full documentation is in the README on GitHub.
Upgrading from 1.x
Plugins built against 1.x keep working without changes. The old methods (initializeDatabase, getDatabase, executeStatement, queryValue, queryRow, queryMultipleRows) are still there and have been fixed. The query methods are deprecated in favour of the safer parameterized ones.
Suggestions & Support
Found a bug or have an idea? Post in the discussion tab, open an issue, or join the Discord:
https://discord.gg/wm6zMzdBwf
Similar projects
Plugin →Let Me Despawn
Improves performance by tweaking mob despawn rules. Say bye to pesky unintentional persistent mobs.
26.2MSueta
JourneyMap
Real-time map used for mapping in-game or your browser as you explore.
14.7MSueta
Emotecraft
Create your own emotes in Minecraft.
7.9MSueta
Simple Tpa
A simple tpa plugin which sends requests
5.4MSueta
Common Network
Forge and Fabric Unified Networking Solution
4.7MSueta
Set Home
A lightweight plugin for players to set their homes.
3.8MSueta