BStore-j
Explicit-first successor line for the Java BStore data access layer.
bstore-j starts as a clean copy of bstore-java, but evolves independently:
- build and publication identity are separate
- the package surface remains familiar
- explicit model definition becomes first-class
- reflection remains available only as optional sugar
- GraalVM-friendlier operation is a design goal
What It Is
bstore-j has two main pieces:
com.reliancy.rec- lightweight structured data types
- JSON-like records, headers, slots, arrays/objects
com.reliancy.dbo- storage-oriented entity/field/record model
- SQL-inspired actions and filters
- SQL backend via
com.reliancy.dbo.sql
The API is inspired by SQL, but the design goal is not to reproduce SQLAlchemy or raw SQL access. The goal is a small, consistent data layer that can later be ported across languages and backed by other systems.
Current Direction
The Java codebase is the reference implementation for:
- CRUD over entities and fields
- backend-neutral
dbocontracts - SQL as the first reference backend
- metadata/migration support through
dbo.meta
The current meta model is intentionally lean:
ChangeEventis the canonical persisted historyDataOriginatoris a module/plugin registry snapshotEntityDefinitionandFieldDefinitionare utility/transient planning models
Core Features
- explicit and reflective entity definition paths
- CRUD with
Terminal,Action,Check, andOrdering - joined inheritance support
- SQL backends for PostgreSQL/MySQL/SQL Server/Oracle/H2
- streaming loads and batched writes
- migration/change discovery through
MetaTerminal - replay-safe structural change application
- startup-oriented migration flow
Status
The library is being revised so that:
- explicit metadata becomes the canonical runtime path
DBOremains the runtime record type- typed non-
DBOmodels can use adapters - reflection and annotation-driven publication remain optional convenience
The active implementation plan lives in:
Explicit-First Example
import com.reliancy.dbo.DBO;
import com.reliancy.dbo.Entity;
import com.reliancy.dbo.Field;
import com.reliancy.dbo.sql.SQLTerminal;
Entity person = Entity.define("public.person")
.setId("person")
.field(
Field.Int("id").setPk(true).setAutoIncrement(true).nullable(false),
Field.Str("name").nullable(false),
Field.Int("age")
)
.publish();
SQLTerminal db = new SQLTerminal("postgres://user:pass@localhost:5432/appdb");
db.meta().migrate("core", "person-v1", person);
DBO alice = DBO.of(person);
alice.set(person.getField("name"), "Alice");
alice.set(person.getField("age"), 30);
db.save(alice);
DBO loaded = db.load(person, alice.get(person.getField("id")));
Optional Sugar Example
import com.reliancy.dbo.DBO;
import com.reliancy.dbo.Entity;
import com.reliancy.dbo.Field;
import com.reliancy.dbo.sugar.BStoreRegistry;
import com.reliancy.dbo.sql.SQLTerminal;
@Entity.Info(name="public.person")
public class Person extends DBO {
public static final Field ID = Field.Int("id").setPk(true).setAutoIncrement(true);
public static final Field NAME = Field.Str("name");
}
SQLTerminal db = new SQLTerminal("postgres://user:pass@localhost:5432/appdb");
BStoreRegistry registry = BStoreRegistry.builder().register(Person.class).build();
registry.publishAll();
db.meta().migrate("core", "person-v1", registry.entity(Person.class));
Person loaded = db.load(registry.adapter(Person.class), 1);
Quick Start
import com.reliancy.dbo.DBO;
import com.reliancy.dbo.Entity;
import com.reliancy.dbo.Field;
import com.reliancy.dbo.sql.SQLTerminal;
@Entity.Info(name="public.person")
public class Person extends DBO {
public static final Field ID = Field.Int("id").setPk(true).setAutoIncrement(true);
public static final Field NAME = Field.Str("name").setTypeParams("255");
public static final Field AGE = Field.Int("age");
}
SQLTerminal db = new SQLTerminal("postgres://user:pass@localhost:5432/appdb");
Person person = new Person();
person.set(Person.NAME, "Alice");
person.set(Person.AGE, 30);
db.save(person);
Person loaded = db.load(Person.class, person.get(Person.ID));
Query Example
import com.reliancy.dbo.Action;
import com.reliancy.dbo.DBO;
try (Action action = db.begin()
.load(Person.class)
.filterBy(Person.AGE.gte(18))
.orderBy(Person.NAME.asc())
.limit(100)
.execute()) {
for (DBO row : action) {
System.out.println(row.get(Person.NAME));
}
}
Startup Migration Example
import com.reliancy.dbo.Entity;
import com.reliancy.dbo.meta.MetaTerminal;
MetaTerminal meta = db.meta(Entity.recall(Person.class));
meta.migrate(
"core-module",
"release-2026-03-17",
Entity.recall(Person.class)
);
Current behavior:
- ensures the required
bstore.change_eventhistory table exists - discovers expected entity structure from code
- discovers actual structure from the backend
- computes ordered structural changes
- applies unapplied changes
- records applied changes in the change log
Module Registry Example
import com.reliancy.dbo.meta.DataOriginator;
DataOriginator module = new DataOriginator();
module.set(DataOriginator.ID, "core-module");
module.set(DataOriginator.ORIGINATOR_ID, "core-module");
module.set(DataOriginator.ORIGINATOR_VERSION, "1.0.0");
module.set(DataOriginator.INSTALLED_VERSION, "1.0.0");
module.set(DataOriginator.DESCRIPTION, "Core application module");
db.save(module);
DataOriginator is meant for module/plugin registry data, not arbitrary module
state and not detailed migration history.
What Is Supported Today
- install-style schema creation
- additive schema upgrades
- safe table rename within the same schema
- replay-safe change application
- schema downgrade by replaying a contraction plan
What Is Intentionally Not Broad Yet
- rich relationship/foreign-key navigation
- generic rollback synthesis
- plugin settings/state storage in meta records
- non-SQL backends in Java
Testing
The curated test suite uses a Postgres database via DB_URL.
export DB_URL="postgres://user:pass@localhost:5432/testdb"
./gradlew test
There are focused integration tests for:
- CRUD and SQL backend behavior
- change discovery ordering
- change replay/idempotency
- startup migration flow
- install/upgrade/downgrade lifecycle at the schema level
Docs
License
GNU Lesser General Public License, Version 3.0