Files
Database/docs/orm.md
2026-01-15 22:38:46 +03:00

3.3 KiB

ORM

The ORM is lightweight: it maps fields to columns and does not manage complex relationships. It supports sync and async operations.

Annotations

  • @DbEntity(table = "players") sets table name. Default: snake_case class name.
  • @DbColumn(name = "username") overrides column name.
  • @DbColumn(type = "VARCHAR(32)") overrides SQL type for schema generation.
  • @DbColumn(length = 32, unique = true, nullable = false) influences schema generation.
  • @DbId(autoIncrement = true) marks the primary key.
  • @DbJson stores the field as JSON.
  • @DbTransient ignores the field.

Example entity

@DbEntity(table = "players")
public class PlayerModel {
    @DbId(autoIncrement = true)
    private long id;

    @DbColumn(name = "username", nullable = false, unique = true, length = 32)
    private String name;

    @DbColumn
    private int level;

    @DbJson
    private java.util.Map<String, Object> metadata;

    @DbTransient
    private String temp;

    public PlayerModel() {
    }
}

CRUD

EntityManager orm = api.orm();

orm.insert(entity);
orm.update(entity);
orm.delete(entity);
PlayerModel player = orm.findById(PlayerModel.class, 1L);
List<PlayerModel> all = orm.findAll(PlayerModel.class);
PlayerModel one = orm.findOneWhere(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10));
List<PlayerModel> many = orm.findWhere(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10));
List<PlayerModel> paged = orm.findWhere(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10), "level DESC", 10, 0);
long count = orm.count(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10));
boolean exists = orm.exists(PlayerModel.class, "username = ?", java.util.Collections.singletonList("Steve"));
int deleted = orm.deleteWhere(PlayerModel.class, "level < ?", java.util.Collections.singletonList(1));

Query Builder

EntityManager orm = api.orm();

List<PlayerModel> top = orm.query(PlayerModel.class)
    .where("level >= ?", 10)
    .orderBy("level DESC")
    .limit(10)
    .list();

boolean exists = orm.query(PlayerModel.class)
    .where("username = ?", "Steve")
    .exists();

Fluent Conditions

import static com.andrewkydev.database.orm.Conditions.*;

List<PlayerModel> players = orm.query(PlayerModel.class)
    .where(eq("status", "ACTIVE").and(gt("level", 10)))
    .list();

Joins, Group By, Having

List<PlayerModel> rows = orm.query(PlayerModel.class)
    .select("players.*")
    .join("LEFT JOIN clans ON clans.id = players.clan_id")
    .groupBy("players.id")
    .having("COUNT(clans.id) > ?", 0)
    .list();

Selecting a subset of columns maps only those fields; missing fields keep default values.

Auto ID on insert

If @DbId(autoIncrement = true) is used and the id is empty (0 or null), insert() will read generated keys and set the id back on the entity.

Custom Type Adapters

UUID mapping is built-in. For other types:

orm.registerAdapter(SomeType.class, new TypeAdapter<SomeType>() {
    @Override
    public Object toDatabase(SomeType value) {
        return value == null ? null : value.toString();
    }

    @Override
    public SomeType fromDatabase(Object value) {
        return value == null ? null : SomeType.parse(value.toString());
    }
});