Get Started

PikaORM is a lightweight ActiveRecord ORM for Java. Map a plain class to a table to get CRUD and a fluent query API, and drop to raw SQL whenever you want. There are no configuration files or annotations to write.

If this is the first time you have worked with a ORM or Database, refer to our Concepts tab to get started!

Install

Add PikaORM to your project (it targets Java 17):

<dependency>
    <groupId>edu.montana.cs.pika</groupId>
    <artifactId>pika-orm</artifactId>
    <version>0.1.0</version>
</dependency>

Add a JDBC driver for your database too — for SQLite:

<dependency>
    <groupId>org.xerial</groupId>
    <artifactId>sqlite-jdbc</artifactId>
    <version>3.49.1.0</version>
</dependency>

See Changelog for the proper version compatibility

Define your schema

Schema lives in code. Extend Migrations and add one PikaMigration per change:

import edu.montana.pika.migrations.Migrations;
import edu.montana.pika.migrations.PikaMigration;

public class AppMigrations extends Migrations {
    @Override
    public void migrations() {
        add(this::createTodos);
    }

    public PikaMigration createTodos() {
        return makeMigration("001_create_todos")
                .up("""
                    CREATE TABLE IF NOT EXISTS todos (
                        id        INTEGER PRIMARY KEY,
                        title     TEXT,
                        completed INTEGER
                    );
                    """)
                .down("DROP TABLE todos;");
    }
}

See Migrations for rollbacks and the interactive CLI.

Define a bean

A domain object is a plain class that extends PikaBean. Fields map to columns by convention — class Todo maps to table todos, field dueDate to column due_date. A static find() gives you a typed entry point for queries.

import edu.montana.pika.bean.PikaBean;
import edu.montana.pika.query.PikaClassFinder;

public class Todo extends PikaBean {
    Long id;
    String title;
    Boolean completed = false;

    public Todo() {}
    public Todo(String title) { this.title = title; }

    public void setCompleted(Boolean completed) { this.completed = completed; }

    public static PikaClassFinder<Todo> find() {
        return find(Todo.class);
    }
}

Connect

Create the ORM once at startup and apply your migrations. makeDefaultORM() registers it as the default instance that backs every bean.

import edu.montana.pika.PikaORM;

PikaORM orm = new PikaORM("jdbc:sqlite:app.db")
        .makeDefaultORM()
        .withMigrations(new AppMigrations())
        .applyMigrations();

CRUD

Beans persist themselves:

// Create
Todo todo = new Todo("Read the docs");
todo.save();                  // INSERT

// Read by primary key
Todo found = Todo.find().byId(1L);

// Update — save() knows it is an existing row
found.setCompleted(true);
found.save();                 // UPDATE

// Delete
found.delete();

Query

find() returns a fluent builder:

import edu.montana.pika.query.PikaList;

PikaList<Todo> open = Todo.find()
        .where("completed = :done", "done", false)
        .fetchList();

Where to next

  • CRUD — the full create/read/update/delete surface
  • Querying — filtering, ordering, joins, and aggregates
  • Validation & Forms — validating beans and binding web form data
  • Cheat Sheet — every operation at a glance