Library / SDK
gaarason/database-all avatar
gaarason/database-all

database-all: an ActiveRecord style ORM for Java

Eloquent ORM for Java 8, 11, 17, 21, 23 and Spring boot 2.x , 3.x

1,014 stars27 forksJavaMIT

At a glance

What is it?
database-all is a Java ORM that takes the ActiveRecord pattern from Laravel's Eloquent and implements it over JDBC, with a chainable query builder, an eager loading relationship API, a code generator for entities and models, and a Spring Boot starter. It supports Java 8 through 23 and Spring Boot 2.x and 3.x.
Who is it for?
Adopt database-all if your team comes from Laravel and wants the ActiveRecord model style in Java, or if you want a query builder with eager loading and a code generator rather than a heavily annotated entity layer. Do not adopt it if your project already standardises on MyBatis or JPA and the team has invested in that mapping style.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Eloquent, ported to Java

database-all is described as an Eloquent ORM for Java, and the name of the project gives away the reference point. The README makes the aim explicit: it makes connecting to a database and performing inserts, deletes, updates, and queries simple, whether you want native SQL, a query builder, or the Eloquent ORM itself.

The Eloquent part is an ActiveRecord implementation. Each data table corresponds to an entity that mirrors the table structure, and a model class is used to interact with it, so through the model you can query, insert, update, and delete rows, and the results are reflected in the Java object instantiated from the entity. The project describes this as a beautiful and simple ActiveRecord for working with databases.

The distinguishing capability, in the project's own framing, is relationships. Eloquent ORM provides expressive declaration methods and concise usage methods for associations, and it focuses on internal query and memory optimisation so that complex relationships still feel good. The documentation has a dedicated page for relationship handling, alongside pages for configuration, mapping, the model, the record result set, the query builder, code generation, unit testing, GraalVM, and version information.

It is a JVM project with a broad compatibility claim: native Java 8, 11, 17, 21, and 23, Spring Boot 2.x and 3.x, compatibility with other common ORM frameworks and common DataSource implementations, and every database that JDBC supports. The project is MIT licensed, its primary language is Java, and the last push to the repository was on 2026-10-13.

The query builder, and the shape of a query

The four operations are expressed as four chains, and the README lists them directly: select is model.newQuery().select().where().get(), update is model.newQuery().data().where().update(), delete is model.newQuery().where().delete(), and insert is model.newQuery().column().value().insert().

The examples show how much of the Laravel feel survives the port. A primary key lookup is one call:

java
// select * from student where id = 4 limit 1
Student student = studentModel.find(4).toObject();

A raw query with parameters goes through the same builder:

java
// select * from student where id = 4 limit 1
Student student = studentModel.newQuery().query("select * from student where id= ? limit ? ", 4, 1).toObject();

Column selection uses method references rather than string names, which is what keeps the query type safe against a renamed field:

java
// select name,age from student where id in (1, 2, 3)
List<Student> students = studentModel.newQuery()
        .select(Student::getName).select(Student::getAge)
        .whereIn(Student::getId, 1, 2, 3)
        .get().toObjectList();

And the closure-style nesting for compound conditions is a direct translation of the PHP original, where each nested builder lambda receives a nested builder:

java
// select id,name from student where id=3 or(age>11 and id=7 and(id between 4 and 10 and age>11))
List<Student> students = studentModel.newQuery().where("id", "3").orWhere(
                builder->builder.where("age", ">", "11").where("id", "7").andWhere(
            builder2->builder2.whereBetween("id", "4", "10").where("age", ">", "11")
        )
).select("id", "name").get().toObjectList();

The result comes back as a Record, which is the project's term for the query result set, and toObjectList() converts it into entity instances. The README notes that the query builder, the SQL syntax, the type conversion, and the relationships are all fully customisable.

Eager loading, which is where the design shows

The relationship example in the README is worth reading closely, because it is the part that is usually where an ActiveRecord port either works or does not. A single query on student, followed by a with() call that names a nested path:

java
// select * from student where id in (1, 2, 3)
// select * from teacher where id in (?, ?, ?)
// select * from father where id in (?, ?, ?)
// select * from house where owner_id in (?, ?, ?)
List<Student> students = studentModel.newQuery().whereIn("id", 1, 2, 3).get().with("teacher.father.house").toObjectList();

Those comments are the actual SQL that is issued, and they show the point. The nested path is resolved with one query per level, and each level is a single query with a parameterised in-list of the parent keys. That is what the project means by internal query and memory optimisation: instead of the N plus 1 problem, where each parent row triggers a child query, the whole result set is fetched per level in a round trip. For a deep chain like teacher.father.house, four queries replace what could be hundreds.

The write-side side of relationships works the same way, through a find and a bind:

java
// select * from student where id = 8 limit 1
// select * from relation_student_teacher where student_id = 8 and teacher_id in (1, 2, 3)
// insert into relation_student_teacher set student_id = 8 and teacher_id = 3
studentModel.findOrFail(8).bind("teachers").attach( 1, 2, 3 );

The attach call takes a varargs list, checks the existing relation rows, and inserts the missing ones. The names, with, bind, and attach, are all the Laravel vocabulary, which means a developer who has written Eloquent queries will not have to learn a new mental model.

The Spring Boot starter, and the coordinate change

The Maven coordinates for the Spring Boot starter are:

xml
<dependency>
    <groupId>io.github.gaarason</groupId>
    <artifactId>database-spring-boot-starter</artifactId>
    <version>{latest-version}</version>
</dependency>

The note underneath is the detail to catch. Because the publishing repository changed, the coordinates differ slightly from those before 7.0.0, with the groupId moving from com.github.gaarason.database-all to io.github.gaarason. A project upgrading across that boundary has to change its groupId, and a copy-pasted snippet from an older article will fail to resolve.

The datasource configuration is standard Spring properties, with a MySQL URL, username, password, and driver class name. Two additions are worth noting. The datasource type can be set to DruidDataSource, so the project adds support for it in the style Spring expects. And there are two commented-out project-specific options, gaarason.database.snow-flake.worker-id, which defaults to 0 and is described as the snowflake algorithm worker id, and gaarason.database.scan.packages, which defaults to the package of your @SpringBootApplication and which the documentation says you should set manually outside Spring Boot.

The scan packages setting is the one that catches people. The framework finds your models by scanning packages, so if your models live somewhere the default scan does not reach, the application starts and then fails to find the model, which reads as a wiring problem rather than a configuration one.

The GeneralModel, for when you do not want to define anything

Not every query needs a generated entity and model, and the project provides a way in for that case. The pre-built GeneralModel requires no additional definitions, so you can query a table by name:

java
@Resource
GeneralModel generalModel;

@Test
public void simpleQuery() {

    // select * from student where id = 3 limit 1
    Record<?, ?> record = generalModel.newQuery().from("student").where("id", 3).firstOrFail();

    // to map
    Map<String, Object> stringObjectMap = record.toMap();

    System.out.println(stringObjectMap);
}

The shape of that is the same builder with a from("student") call instead of a typed model, and the result is a Record rather than a typed entity, which you can turn into a map with toMap(). This is the same pattern as Eloquent's generic base, and it is what you use for a one-off query against a table you do not want to model yet, for a reporting query, or during an exploration of an unfamiliar schema.

The full experience adds the code generator on top, which automates the definition of an entity matching each table's structure along with the model used to interact with it. The declared annotations on the entity handle the mapping, and the model then exposes the query builder, the Record result set, and the relationship methods.

The module layout, and the alternative to ActiveRecord

The top level directories map onto the documentation's structure, which is a useful hint about the layering. database-api is the public surface, database-core holds the implementation, database-query is the query builder, database-logging is the logging integration, database-generator is the code generator, database-spring-boot-starter is the Spring integration, database-tests is the test suite, and document/ holds the documentation pages that the README links.

The alternative to this style of ORM is the one most Java teams already use, and the difference is worth stating honestly. With JPA and Hibernate, the mapping is declarative through annotations, the entity is a Java class you write by hand or generate, and the query mechanism is JPQL, a Criteria API, or a specification object. With MyBatis, the SQL is written by hand and a mapper interface sits over it.

database-all sits between those, and closer to the MyBatis end in one respect. It keeps the query builder chainable and the SQL visible, and it adds a convenience layer on top for relationships and eager loading. The ActiveRecord style, where the model both describes the table and is the entry point for operations, is the part that is unusual in the Java world, and it is the part that will feel either familiar or wrong depending on where you came from.

The project's compatibility claim includes other common ORM frameworks and common DataSource implementations, which in practice means it sits on JDBC and can run alongside an existing persistence setup rather than replacing it wholesale. The GraalVM page in the documentation is worth a look if you are compiling to a native image, since reflection-based ORMs and annotation processors are a common source of trouble there.

Editorial conclusion

Adopt database-all if your team comes from Laravel and wants the ActiveRecord model style in Java, or if you want a query builder with eager loading and a code generator rather than a heavily annotated entity layer. Do not adopt it if your project already standardises on MyBatis or JPA and the team has invested in that mapping style. Verify first that the coordinates are right for your version, because the groupId changed to io.github.gaarason and the earlier com.github.gaarason.database-all form applies only to versions before 7.0.0.

Frequently asked questions

What is database-all and what style of ORM does it implement?

database-all is an Eloquent ORM for Java, an ActiveRecord implementation where each data table corresponds to an entity and a model class through which you query, insert, update, and delete rows, with the results reflected in the Java object.

What are the Maven coordinates for the database-all Spring Boot starter?

The groupId is io.github.gaarason, the artifactId is database-spring-boot-starter, and the version comes from the latest-version badge. The note in the documentation says the groupId changed from com.github.gaarason.database-all, so coordinates differ from versions before 7.0.0.

How does database-all handle relationships and eager loading?

Relationships are declared with expressive annotations and resolved with an eager loading call such as with("teacher.father.house"). The documented SQL shows one parameterised query per level of the nested path, so a deep chain takes a few round trips rather than one query per parent row.

Can I query a table without generating an entity and model?

Yes. The pre-built GeneralModel needs no additional definitions, so you can write generalModel.newQuery().from("student").where("id", 3).firstOrFail() and get a Record, which you can convert with toMap() into a map of column values.

Which Java and Spring Boot versions does database-all support?

The project lists JDK 8, 11, 17, 21, and 23 badges, and supports Spring Boot 2.x and 3.x. It is compatible with other common ORM frameworks and DataSource implementations, and with any database that JDBC supports.

Official sources

  1. gaarason/database-all on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/gaarason-database-all.svg)](https://hysenlabs.com/projects/gaarason-database-all)

Was this useful?