Spruce: Modern JDBC

Spruce: Fresh, trim, & lightweight JDBC wrapper

I originally released this project a while back, but I wanted to let it stabilize a bit before publicizing it more. I’ve not needed to commit any changes in quite some time, so I guess now’s as good a time as any to bring it up (though I do have plans for mapping Java classes to/from SQL tables, which may be able to be somewhat automated for record types). It’s certainly handy for persisting game data - even if I were just doing save files (as opposed to the networked server-based persistence project I’m working on now), I’d probably use SQLite or a similar in-process SQL database.

The primary motivation behind Spruce is that while JDBC is the standard for DB access from Java, it’s an old API that’s quite verbose. I’ve used a number of DB wrappers in other languages that are much more concise and make good use of more modern language features (such as functional constructs), but I was missing something like that in Java. Most wrappers at the very least try to be SQL code generators as well (which sounds great until you need to access operators or DB functions that aren’t as commonly used), and many quickly get into ORM functions as well. I wanted something minimalistic (coding directly against the DB) and lightweight that would let me concisely express my intentions without much ceremony. Spruce does that, and supports the concept of “modules” (which are just data access objects) for organizing your database code. I use Spruce exclusively for all database access in the MyWorld project, and it’s served me well so far.

It’s an extremely small library (the primary class is only ~150 LOC), but I find it has a rather outsized impact on my DB code. It supports basic SQL access patterns (modify & query), and it also supports batching and transactions with very little code beyond the basics. It’s very explicitly not an ORM and never will be - though as I mentioned above I do have plans to add support for mapping objects to/from DB rows (possibly constrained to record types). Eventually I may also add support for DB evolutions.

The README has a fairly complete set of examples that demonstrate its common usage patterns.