Skip to content

Quick Start

Petrus Pradella edited this page Jul 5, 2026 · 6 revisions

Quick Start

Basic Usage

The lifecycle is describe → open → use → close. Everything between init() and close() is backend-agnostic. Entities are plain POJOs.

import br.com.finalcraft.everydatabase.*;
import br.com.finalcraft.everydatabase.codec.JacksonJsonCodec;
import br.com.finalcraft.everydatabase.modules.sql.SqlConfig;

import java.util.Optional;
import java.util.UUID;

// 1. A plain entity — no-arg constructor + accessors so Jackson can (de)serialise it.
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PlayerEntity { // POJO (Plain Old Java Object)
  private UUID uuid;
  private String name;
  private int score;
  private SomeInnerData innerData; // Another POJO
}

// 2. Create an EntityDescriptor for the Entity.
EntityDescriptor<UUID, PlayerEntity> PLAYERS = EntityDescriptor.builder(UUID.class, PlayerEntity.class)
  .collection("player")
  .keyExtractor(PlayerEntity::getUuid)
  .codec(new JacksonJsonCodec<>(PlayerEntity.class))
  .build();

// 3. Pick a storage backend and open it.
Storage storage = Storages.createSQL(
  new SqlConfig(
    "jdbc:mariadb://localhost:3306/mydb",
    "root",
    "root")
);

storage.init().join();

// 4. Create a typed repository on that database.
Repository<UUID, PlayerEntity> repo = storage.repository(PLAYERS);

UUID aliceId = UUID.randomUUID();
repo.save(
  new PlayerEntity(aliceId, "Alice", 100)
).join(); // upsert

Optional<PlayerEntity> alice = repo.find(aliceId).join(); // -> Optional[Alice]
long total = repo.count().join();                         // -> 1

// 5. Release the pool when you're done or the application ends.
storage.close().join();

Why .join() everywhere?

Every I/O call returns a CompletableFuture — there are no blocking variants. .join() waits for the result, keeping these examples short. In real code you compose instead of blocking:

repo.find(aliceId)
  .thenApply(opt -> opt.map(PlayerEntity::getScore).orElse(0))
  .thenAccept(score -> System.out.println("score = " + score));

Errors surface as the exceptional completion of the future (as the cause of a CompletionException when you .join()). The full async model — composition, exception handling, the executor — is on The Async API.


Swapping the backend is one line

Everything from storage.repository(PLAYERS) downward is identical on every engine. To move onto MongoDB, change only how you open the storage:

import br.com.finalcraft.everydatabase.modules.mongo.MongoConfig;

Storage storage = Storages.createMongo(
  new MongoConfig(
    "mongodb://localhost:27017",
    "mydb")
);

storage.init().join();

// ...repository(PLAYERS), save, find, count — all unchanged

Or an embedded H2 file, or pure in-memory for a test:

Storage h2  = Storages.createH2(new SqlConfig("jdbc:h2:file:./data/storage", "", ""));
Storage mem = Storages.createInMemory();

See Choosing a Backend for the capability matrix and per-backend setup, and the per-engine config (SqlConfig, MongoConfig, LocalFileConfig) on each backend's page.


See also

  • Defining EntitiesEntityDescriptor.builder, collection rules, valid keys, codecs.
  • The Async API — the CompletableFuture model, composition, exceptional completion.
  • CRUD Operationsfind / findMany / save / saveAll / delete / exists / count / all.
  • Choosing a Backend — the capability matrix and per-backend instantiation.
  • Installation — coordinates and flavor choice.

Clone this wiki locally