Getting Started
Install Tava, choose an adapter, define a schema, and run a small query.
Tava is published as small modules. Import the BOM, add tava-core, then add only
the adapters your application actually opens.
dependencies {
implementation(platform("eu.mikart.tava:tava-bom:1.0.0"))
implementation("eu.mikart.tava:tava-core")
implementation("eu.mikart.tava:tava-postgres")
}Java version
Tava is compiled for Java 21. Configure your application toolchain before adding the modules.
Install
dependencies {
implementation(platform("eu.mikart.tava:tava-bom:1.0.0"))
implementation("eu.mikart.tava:tava-core")
implementation("eu.mikart.tava:tava-postgres")
}Pick An Adapter
Every adapter returns the same SPI type, so application code opens Tava the same
way regardless of backend.
import eu.mikart.tava.Tava;
import eu.mikart.tava.postgres.Postgres;
try (Tava tava = Tava.open(Postgres.connect(jdbcUrl, user, password))) {
System.out.println(tava.adapterName());
}For local tests, H2 and SQLite keep the setup short:
import eu.mikart.tava.Tava;
import eu.mikart.tava.h2.H2;
import eu.mikart.tava.sqlite.Sqlite;
try (Tava h2 = Tava.open(H2.memory("tests"))) {
// Fast in-memory JDBC adapter.
}
try (Tava sqlite = Tava.open(Sqlite.memory("tests"))) {
// Shared in-memory SQLite database kept alive until Tava closes.
}Define A Record
Records are the most compact way to define typed entities. Tava derives the entity name, field names, nullability, logical types, uniqueness, identity fields, and generated values from annotations and Java component types.
import eu.mikart.tava.schema.GeneratedValue;
import eu.mikart.tava.schema.annotation.Entity;
import eu.mikart.tava.schema.annotation.Field;
import eu.mikart.tava.schema.annotation.Generated;
import eu.mikart.tava.schema.annotation.Identity;
import eu.mikart.tava.schema.annotation.Required;
import eu.mikart.tava.schema.annotation.Unique;
import java.time.Instant;
import java.util.UUID;
@Entity("accounts")
public record Account(
@Identity UUID id,
@Required @Unique @Field(length = 255) String email,
int score,
@Generated(GeneratedValue.NOW) Instant createdAt
) {}Apply The Schema
Schema changes are planned before they are applied. Unsupported changes fail. Lossy or destructive changes require an explicit opt-in.
import eu.mikart.tava.schema.Schema;
Schema schema = Schema.builder()
.record(Account.class)
.build();
try (Tava tava = Tava.open(Postgres.connect(jdbcUrl, user, password))) {
var plan = tava.plan(schema);
plan.changes().forEach(change ->
System.out.println(change.risk() + " " + change.description()));
plan.apply();
}Insert And Query
import eu.mikart.tava.query.Predicate;
import eu.mikart.tava.query.Query;
import eu.mikart.tava.query.Sort;
var accounts = tava.entity(Account.class);
Account saved = accounts.insert(new Account(
UUID.randomUUID(),
"ada@example.com",
7,
null
));
var page = accounts.find(Query.builder()
.where(Predicate.eq("email", saved.email()))
.sort(Sort.desc("createdAt"))
.limit(25)
.build());Last updated on
Last updated on