Doma is a database access framework that runs on Java 8 and above. You can access databases for which JDBC drivers are provided, such as MySQL, PosgreSQL, Microsoft SQL Sever, and H2 Database.
Recent versions of Doma have added a new API for type-safe SQL construction, the Criteira API (https://doma.readthedocs.io/en/2.43.0/criteria-api/). This article introduces the Criteria API based on the latest version 2.43.0 at the time of writing.
Suppose you have a database schema that looks like this:
create table employee (
id integer not null primary key,
name varchar(255) not null,
age integer not null,
version integer not null);
The entity class corresponding to the above table can be defined as follows:
@Entity(metamodel = @Metamodel)
public class Employee {
@Id
public Integer id;
public String name;
public Integer age;
@Version public Integer version;
}
At first glance, it's a normal entity class definition, but notice that the @ Entity
declaration says metamodel = @Metamodel
. This description is very important, and compiling with the proper settings will generate a metamodel class called `ʻEmployee_`` in the same package as the Employee class.
For the sake of clarity, I'll omit it a bit, but the metamodel class ʻEmployee_` looks like this:
public final class Employee_ implements EntityMetamodel<Employee> {
public final PropertyMetamodel<java.lang.Integer> id = ...;
public final PropertyMetamodel<java.lang.String> name = ...;
public final PropertyMetamodel<java.lang.Integer> age = ...;
public final PropertyMetamodel<java.lang.Integer> version = ...;
}
The point of this metamodel class is that it has properties with the same names as the properties of the entity class, such as ʻid,
name, ʻage
, version
. It also has property type information in the entity class.
The following is an example of actually constructing SQL using this metamodel class and the Criteria API.
The Criteria API can be used anywhere, but it will be easier to understand if you create a class named xxxRepository and use it in it, for example:
public class EmployeeRepository {
private final Entityql entityql;
public EmployeeRepository(Config config) {
this.entityql = new Entityql(config);
}
public Employee selectById(Integer id) {
//Metamodel generation
Employee_ e = new Employee_();
//Assemble SQL using metamodel and get result
return entityql.from(e).where(c -> c.eq(e.id, id)).fetchOne();
}
}
The content of the selectById
method of the above class is an example of using the Criteria API. This method uses the metamodel class and the ʻEntityql` class, which is the entry point of the Criteria API, to assemble SQL and get the execution result as one entity.
The SQL that can be assembled looks like this:
select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where t0_.id = ?
From a type-safe point of view, the point is the ʻeqmethod in the
where (c-> c.eq (e.id, id))` that constructs the WHERE clause. This method utilizes generics to determine the type of the first argument to the type of the second argument at compile time.
In other words, in this example, the type of the second argument is determined to be the ʻInteger type by passing the property representing the ʻInteger
type of the metamodel class to the first argument of the ʻeqmethod. Therefore, it prevents passing an incorrect type to the second argument (resulting in an error at runtime), for example
c.eq (e.id," String value ")`. ..
Using the example of getting an entity, I showed that Doma's Criteri API can be type-safe to construct SQL.
The equivalent of the code shown here is available from the project below.
Recommended Posts