Skip to content

Commit 0c8c768

Browse files
authored
Support Kotlin 1.4.0 or later (#565)
* Improve Kotlin documentation * Improve Doma introduction
1 parent d69bfce commit 0c8c768

File tree

4 files changed

+166
-73
lines changed

4 files changed

+166
-73
lines changed

README.md

Lines changed: 61 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ Doma 2 is a database access framework for Java 8+.
55
Doma has various strengths:
66

77
- Verifies and generates source code **at compile time** using [annotation processing][apt].
8-
- Maps database columns to user-defined Java objects.
9-
- Uses SQL templates, called “two-way SQL”.
10-
- Supports classes introduced in Java 8, such as `java.time.LocalDate`, `java.util.Optional`, and `java.util.stream.Stream`.
8+
- Provides type-safe Criteria API.
9+
- Supports Kotlin.
10+
- Uses SQL templates, called "two-way SQL".
1111
- Has no dependence on other libraries.
1212

1313
[![Build Status](https://github.com/domaframework/doma/workflows/Java%20CI%20with%20Gradle/badge.svg)](https://github.com/domaframework/doma/actions?query=workflow%3A%22Java+CI+with+Gradle%22)
@@ -20,47 +20,74 @@ Doma has various strengths:
2020
Examples
2121
---------------------
2222

23-
Define an entity class:
23+
## type-safe Criteria API
24+
25+
Written in Java 8:
26+
2427
```java
25-
@Entity
26-
public class Employee {
27-
@Id
28-
@GeneratedValue(strategy = GenerationType.SEQUENCE)
29-
@SequenceGenerator(sequence = "EMPLOYEE_SEQ")
30-
public Integer id;
31-
public String name;
32-
public Integer age;
33-
@Version
34-
public Integer version;
35-
}
28+
Entityql entityql = new Entityql(config);
29+
Employee_ e = new Employee_();
30+
Department_ d = new Department_();
31+
32+
List<Employee> list =
33+
entityql
34+
.from(e)
35+
.innerJoin(d, on -> on.eq(e.departmentId, d.departmentId))
36+
.where(c -> c.eq(d.departmentName, "SALES"))
37+
.associate(
38+
e,
39+
d,
40+
(employee, department) -> {
41+
employee.setDepartment(department);
42+
department.getEmployeeList().add(employee);
43+
})
44+
.fetch();
45+
```
46+
47+
Written in Kotlin:
48+
49+
```kotlin
50+
val entityql = KEntityql(config)
51+
val e = Employee_()
52+
val d = Department_()
53+
54+
val list = entityql
55+
.from(e)
56+
.innerJoin(d) { eq(e.departmentId, d.departmentId) }
57+
.where { eq(d.departmentName, "SALES") }
58+
.associate(e, d) { employee, department ->
59+
employee.department = department
60+
department.employeeList += employee
61+
}
62+
.fetch()
3663
```
3764

38-
Define a DAO interface:
65+
## two-way SQL
66+
67+
DAO interface written in Java 8:
68+
3969
```java
40-
@Dao(config = AppConfig.class)
70+
@Dao
4171
public interface EmployeeDao {
42-
@Select
43-
Employee selectById(Integer id);
44-
@Update
45-
int update(Employee employee);
72+
73+
@Select
74+
List<Employee> selectByExample(Employee e);
4675
}
4776
```
4877

49-
Execute queries:
50-
```java
51-
public class App {
52-
public static void main(String[] args) {
53-
TransactionManager tm = AppConfig.singleton().getTransactionManager();
54-
tm.required(() -> {
55-
EmployeeDao dao = new EmployeeDaoImpl();
56-
Employee employee = dao.selectById(1);
57-
employee.age++;
58-
dao.update(employee);
59-
});
60-
}
61-
}
78+
selectByExample.sql:
79+
80+
```sql
81+
select * from EMPLOYEE where
82+
/*%if e.employeeNo > 7800*/
83+
/*%if e.managerId != null*/
84+
salary >= /*e.salary*/9999
85+
/*%end*/
86+
/*%end*/
6287
```
6388

89+
## Other Examples
90+
6491
Try following getting started examples:
6592
- [Get started! (IntelliJ IDEA)](https://doma.readthedocs.io/en/latest/getting-started-idea/)
6693
- [Get started! (Eclipse)](https://doma.readthedocs.io/en/latest/getting-started-eclipse/)

docs/criteria-api.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@ Criteria API
88
Introduction
99
============
1010

11+
.. note::
12+
13+
In Kotlin environment, use Kotlin specific DSLs instead of the following DSLs.
14+
See :ref:`kotlin-specific-criteria-api`.
15+
1116
There are two kinds of DSLs in the Criteria API:
1217

1318
* The Entityql DSL
1419
* The NativeSql DSL
1520

16-
Both require predefined Entity classes and metamodel classes.
21+
Both requires predefined Entity classes and metamodel classes.
1722

1823
We use the following Entity classes to show you some examples:
1924

docs/index.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ Doma 2 is a database access framework for Java 8+.
1616
Doma has various strengths:
1717

1818
* Verifies and generates source code at compile time using annotation processing.
19-
* Maps database columns to user-defined Java objects.
19+
* Provides type-safe Criteria API.
20+
* Supports Kotlin.
2021
* Uses SQL templates, called "two-way SQL".
21-
* Supports classes introduced in Java 8, such as ``java.time.LocalDate``,
22-
``java.util.Optional``, and ``java.util.stream.Stream``.
2322
* Has no dependence on other libraries.
2423

2524
This document consists of following sections:

docs/kotlin-support.rst

Lines changed: 97 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,40 @@ Kotlin support
55
.. contents::
66
:depth: 3
77

8-
Doma supports `Kotlin <https://kotlinlang.org/>`_ 1.3.11 or above **experimentally**.
8+
Doma supports `Kotlin <https://kotlinlang.org/>`_ 1.4.0 or later.
99

1010
Best practices
1111
==============
1212

13-
We show you recommended ways to define classes and build them with Kotlin.
13+
Here are some recommended methods, such as defining classes and building them with Kotlin.
1414

1515
Entity classes
1616
--------------
1717

18-
* Define as a data class
19-
* Specify ``true`` to the ``immutable`` element of ``@Entity``
20-
* Define only one constructor
21-
* Define properties only in the constructor
22-
* Use `val` for the property definitions
18+
* Define as a plain class
19+
* Specify a ``Metamodel`` annotation to the ``metamodel`` element of ``@Entity``
2320

2421
.. code-block:: java
2522
26-
@Entity(immutable = true)
27-
data class Person(
23+
@Entity(metamodel = Metamodel())
24+
class Person : AbstractPerson() {
25+
2826
@Id
2927
@GeneratedValue(strategy = GenerationType.IDENTITY)
30-
val id: Int? = null,
31-
val name: Name,
32-
val address: Address)
28+
var id: Int = -1
29+
30+
var name: Name? = null
31+
32+
var age: Int? = -1
33+
34+
var address: Address? = null
35+
36+
@Column(name = "DEPARTMENT_ID")
37+
var departmentId: Int = -1
38+
39+
@Version
40+
var version: Int = -1
41+
}
3342
3443
Domain classes
3544
--------------
@@ -88,41 +97,94 @@ Dao interfaces
8897
val person = Person(name = Name("Jhon"), address = Address(city = "Tokyo", street = "Yaesu"))
8998
val (newPerson, count) = dao.insert(person)
9099
91-
Using kapt in Gradle
92-
--------------------
100+
.. _kotlin-specific-criteria-api:
93101
94-
Annotation processors are supported in Kotlin with the
95-
`kapt <https://kotlinlang.org/docs/reference/kapt.html>`_ compiler plugin.
102+
Kotlin specific Criteria API
103+
----------------------------
96104
97-
Add the dependencies using the `kapt` and `implementation` configuration in your dependencies block:
105+
.. note::
98106
99-
.. code-block:: groovy
107+
Prefer the Kotlin specific Criteria API to DAO interfaces.
100108
101-
dependencies {
102-
implementation "org.seasar.doma:doma-core:2.41.0"
103-
kapt "org.seasar.doma:doma-processor:2.41.0"
104-
}
109+
Doma provides Kotlin specific Criteria API, ``KEntityql`` and ``KNativeQl`` DSLs.
110+
They are very similar with the ``Entityql`` and ``NativeQl`` DSLs, which are described in :doc:`criteria-api`.
111+
The biggest feature of the ``KEntityql`` and ``KNativeQl`` DSLs is simplicity.
105112
106-
To simplify your build.script, we recommend you use
107-
the `Doma Compile Plugin <https://github.com/domaframework/doma-compile-plugin>`_:
113+
For example, when you use ``KEntityql``, you have to accept a lambda parameter in a WHERE expression as follows:
108114
109-
.. code-block:: groovy
115+
.. code-block:: kotlin
110116
111-
plugins {
112-
id 'org.seasar.doma.compile' version '1.1.0'
113-
}
117+
val entityql = Entityql(config)
118+
val e = Employee_()
114119
115-
For more details, see this `build.gradle <https://github.com/domaframework/kotlin-sample/blob/master/build.gradle>`_.
120+
val list = entityql
121+
.from(e)
122+
.where { c ->
123+
c.eq(e.departmentId, 2)
124+
c.isNotNull(e.managerId)
125+
c.or {
126+
c.gt(e.salary, Salary("1000"))
127+
c.lt(e.salary, Salary("2000"))
128+
}
129+
}
130+
.fetch()
116131
117-
.. note::
132+
The lambda parameter ``c`` is a bit annoying.
133+
On the other hand, when you use ``KEntityql``, the parameter is gone.
134+
135+
.. code-block:: kotlin
136+
137+
val entityql = KEntityql(config)
138+
val e = Employee_()
139+
140+
val list = entityql
141+
.from(e)
142+
.where {
143+
eq(e.departmentId, 2)
144+
isNotNull(e.managerId)
145+
or {
146+
gt(e.salary, Salary("1000"))
147+
lt(e.salary, Salary("2000"))
148+
}
149+
}
150+
.fetch()
151+
152+
You can see a lot of sample code `here<https://github.com/domaframework/doma-it/tree/master/kotlin/src/test/kotlin/org/seasar/doma/it/criteria>`_.
153+
154+
The ``KEntityql`` and ``KNativeQl`` DSLs are included in doma-kotlin.jar.
155+
Note that you should depend on doma-kotlin instead of doma-core in your build script.
156+
You can write build.gradle.kts as follows:
157+
158+
.. code-block:: kotlin
159+
160+
dependencies {
161+
implementation("org.seasar.doma:doma-kotlin:2.41.0")
162+
}
163+
164+
Code Generation
165+
---------------
118166
119-
Remember that you always have options as follows:
167+
Use `Doma CodeGen Plugin <https://github.com/domaframework/doma-codegen-plugin>`_.
168+
This plugin support Kotlin code generation.
120169
121-
- Write all code in Kotlin
122-
- Write all code in Java
123-
- Write code annotated with Doma's annotations in Java and others in Kotlin
170+
Using kapt in Gradle
171+
--------------------
172+
173+
Annotation processors are supported in Kotlin with the
174+
`kapt <https://kotlinlang.org/docs/reference/kapt.html>`_ compiler plugin.
124175
125-
The third option is worth considering, because it can avoid some troubles with the kapt.
176+
Add the dependencies using the `kapt` and `implementation` configuration in your dependencies block.
177+
For example, you can write build.gradle.kts as follows:
178+
179+
.. code-block:: kotlin
180+
181+
dependencies {
182+
kapt("org.seasar.doma:doma-processor:2.41.0")
183+
implementation("org.seasar.doma:doma-kotlin:2.41.0")
184+
}
185+
186+
To simplify your build script, we recommend you use
187+
the `Doma Compile Plugin <https://github.com/domaframework/doma-compile-plugin>`_:
126188
127189
Sample project
128190
==============

0 commit comments

Comments
 (0)