Skip to content

Commit 9ab5653

Browse files
committed
Kotlin のサポートについてドキュメントを追加
2 parents bb898eb + 533e165 commit 9ab5653

11 files changed

+136
-99
lines changed

docs/sources/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ User Documentation
5151
transaction
5252
annotation-processing
5353
build
54+
kotlin-support
5455

5556
Developer Documentation
5657
=======================

docs/sources/kotlin-support.rst

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
==================
2+
Kotlin サポート
3+
==================
4+
5+
.. contents:: 目次
6+
:depth: 3
7+
8+
Doma は `Kotlin <https://kotlinlang.org/>`_ を実験的にサポートしています。
9+
10+
Kotlin利用のベストプラクティス
11+
================================
12+
13+
クラスの定義やビルドに関する事柄について推奨する方法を記載します。
14+
15+
エンティティクラス
16+
-------------------
17+
18+
* Data Classで定義する
19+
* イミュータブルで定義する( `@Entity` の `immutable` 要素に `true` を設定する)
20+
* コンストラクタは1つだけ定義する
21+
* コンストラクタ以外でプロパティを定義しない
22+
* コンストラクタで定義するプロパティには `val` を使用する
23+
* 継承は使わない
24+
25+
.. code-block:: java
26+
27+
@Entity(immutable = true)
28+
data class Person(
29+
@Id
30+
@GeneratedValue(strategy = org.seasar.doma.GenerationType.IDENTITY)
31+
val id: Int? = null,
32+
val name: Name,
33+
val address: Address)
34+
35+
ドメインクラス
36+
-------------------
37+
38+
* Data Classで定義する
39+
* コンストラクタは1つだけ定義する
40+
* コンストラクタで定義するプロパティの名前は `value` にする
41+
* コンストラクタで定義するプロパティには `val` を使用する
42+
43+
.. code-block:: java
44+
45+
@Domain(valueType = String::class)
46+
data class Name(val value: String)
47+
48+
エンベッダブルクラス
49+
----------------------
50+
51+
* Data Classで定義する
52+
* コンストラクタは1つだけ定義する
53+
* コンストラクタ以外でプロパティを定義しない
54+
* コンストラクタで定義するプロパティには `val` を使用する
55+
* 継承は使わない
56+
57+
.. code-block:: java
58+
59+
@Embeddable
60+
data class Address(val city: String, val street: String)
61+
62+
Daoインタフェース
63+
-------------------
64+
65+
* SQLファイルとマッピングする場合は `@ParameterName` を使ってメソッドのパラメータに名前をつける
66+
* 更新処理の戻り値の型は `org.seasar.doma.jdbc.Result` や `org.seasar.doma.jdbc.BatchResult` を使う
67+
68+
.. code-block:: java
69+
70+
@Dao(config = AppConfig::class)
71+
interface PersonDao {
72+
@Select
73+
fun selectById(@ParameterName("id") id: Int): Person
74+
@Insert
75+
fun insert(person: Person): Result<Person>
76+
}
77+
78+
* 更新処理の戻り値を扱う際は `Destructuring Declarations <https://kotlinlang.org/docs/reference/multi-declarations.html>`_ を使う
79+
80+
.. code-block:: java
81+
82+
val dao: PersonDao = ...
83+
val person = Person(name = Name("Jhon"), address = Address(city = "Tokyo", street = "Yaesu"))
84+
val (newPerson, count) = dao.insert(person)
85+
86+
87+
katpによるビルド
88+
-------------------
89+
90+
Kotlin で記述されたクラスやインタフェースに対して注釈処理をするには `kapt <http://blog.jetbrains.com/kotlin/2015/06/better-annotation-processing-supporting-stubs-in-kapt/>`_ を実行する必要があります。
91+
2016年5月現在、Kotlin 1.0.2のkaptは機能が不足しておりかつ動作が不安定です。また、ドキュメントがありません。
92+
Daoインタフェースで `@ParameterName` を用いて明示的に名前をつけることを推奨するのも kapt の不具合に由来します。
93+
不安定な挙動を避けるため、Gradleでビルドする際、常に `clean build` を実行することを推奨します。
94+
95+
.. code-block:: sh
96+
97+
./gradlew clean build
98+
99+
Eclispeを利用する場合設定を適切に行えばJavaの注釈処理は自動で行われますが、kapt(Kotlinの注釈処理)はGradleを実行しない限り行われないことに注意してください。
100+
101+
JavaとKotlinの混在
102+
-------------------------
103+
104+
kaptの不具合を避けるため、Domaに関するコードの全てもしくは一部をJavaで書くことは検討に値します。
105+
特に、DaoについてはJavaで書いても良いかもしれません。
106+
JavaとKotlinで記述量にほとんど差がなく、 `@ParameterName` を使う必要性を避けられるためです。
107+
Domaの利用において、JavaとKotlinの混在は特に問題ありません。
108+
109+
サンプルプロジェクト
110+
=====================
111+
112+
サンプルコードについては下記のプロジェクトを参照ください。
113+
114+
* `kotlin-sample <https://github.com/domaframework/kotlin-sample>`_

src/main/java/org/seasar/doma/internal/apt/EntityTypeGenerator.java

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,6 @@ protected void printPropertyTypeFields() {
184184
newWrapperExpr = String.format("new %s()",
185185
wrapperCtType.getTypeName());
186186
}
187-
String parentEntityPropertyType = "null";
188-
String parentEntityBoxedTypeName = Object.class.getName();
189-
if (!pm.isOwnProperty()) {
190-
parentEntityPropertyType = pm.getEntityMetaTypeName()
191-
+ ".getSingletonInternal()." + pm.getFieldName();
192-
parentEntityBoxedTypeName = pm.getEntityTypeName();
193-
}
194187
String domainType = "null";
195188
String domainTypeName = "Object";
196189
if (domainCtType != null) {
@@ -207,8 +200,8 @@ protected void printPropertyTypeFields() {
207200
/* 6 */entityMeta.getEntityTypeName(),
208201
/* 7 */newWrapperExpr, /* 8 */domainType,
209202
/* 9 */pm.getBoxedTypeName(),
210-
/* 10 */parentEntityPropertyType,
211-
/* 11 */parentEntityBoxedTypeName,
203+
/* 10 */NULL,
204+
/* 11 */Object.class.getName(),
212205
/* 12 */pm.getFieldName(),
213206
/* 13 */pm.getBoxedClassName(),
214207
/* 14 */domainTypeName,
@@ -222,8 +215,8 @@ protected void printPropertyTypeFields() {
222215
/* 6 */entityMeta.getEntityTypeName(),
223216
/* 7 */newWrapperExpr, /* 8 */domainType,
224217
/* 9 */pm.getBoxedTypeName(),
225-
/* 10 */parentEntityPropertyType,
226-
/* 11 */parentEntityBoxedTypeName,
218+
/* 10 */NULL,
219+
/* 11 */Object.class.getName(),
227220
/* 12 */pm.getFieldName(),
228221
/* 13 */pm.getBoxedClassName(),
229222
/* 14 */domainTypeName,
@@ -238,8 +231,8 @@ protected void printPropertyTypeFields() {
238231
/* 6 */entityMeta.getEntityTypeName(),
239232
/* 7 */newWrapperExpr, /* 8 */domainType,
240233
/* 9 */pm.getBoxedTypeName(),
241-
/* 10 */parentEntityPropertyType,
242-
/* 11 */parentEntityBoxedTypeName,
234+
/* 10 */NULL,
235+
/* 11 */Object.class.getName(),
243236
/* 12 */pm.getFieldName(),
244237
/* 13 */pm.getBoxedClassName(),
245238
/* 14 */domainTypeName,
@@ -255,8 +248,8 @@ protected void printPropertyTypeFields() {
255248
/* 8 */entityMeta.getEntityTypeName(),
256249
/* 9 */newWrapperExpr, /* 10 */domainType,
257250
/* 11 */pm.getBoxedTypeName(),
258-
/* 12 */parentEntityPropertyType,
259-
/* 13 */parentEntityBoxedTypeName,
251+
/* 12 */NULL,
252+
/* 13 */Object.class.getName(),
260253
/* 14 */pm.getFieldName(),
261254
/* 15 */pm.getBoxedClassName(),
262255
/* 16 */domainTypeName,
@@ -587,40 +580,30 @@ protected void printGetIdPropertyTypesMethod() {
587580
}
588581

589582
protected void printGetGeneratedIdPropertyTypeMethod() {
590-
String parentEntityTypeNameAsTypeParameter = Object.class.getName();
591583
String idName = "null";
592584
if (entityMeta.hasGeneratedIdPropertyMeta()) {
593585
EntityPropertyMeta pm = entityMeta.getGeneratedIdPropertyMeta();
594586
idName = pm.getFieldName();
595-
if (!pm.isOwnProperty()) {
596-
parentEntityTypeNameAsTypeParameter = pm.getEntityTypeName();
597-
}
598587
}
599588
iprint("@Override%n");
600589
iprint("public %1$s<%3$s, %2$s, ?, ?> getGeneratedIdPropertyType() {%n",
601590
GeneratedIdPropertyType.class.getName(),
602-
entityMeta.getEntityTypeName(),
603-
parentEntityTypeNameAsTypeParameter);
591+
entityMeta.getEntityTypeName(), Object.class.getName());
604592
iprint(" return %1$s;%n", idName);
605593
iprint("}%n");
606594
print("%n");
607595
}
608596

609597
protected void printGetVersionPropertyTypeMethod() {
610-
String parentEntityTypeNameAsTypeParameter = Object.class.getName();
611598
String versionName = "null";
612599
if (entityMeta.hasVersionPropertyMeta()) {
613600
EntityPropertyMeta pm = entityMeta.getVersionPropertyMeta();
614601
versionName = pm.getFieldName();
615-
if (!pm.isOwnProperty()) {
616-
parentEntityTypeNameAsTypeParameter = pm.getEntityTypeName();
617-
}
618602
}
619603
iprint("@Override%n");
620604
iprint("public %1$s<%3$s, %2$s, ?, ?> getVersionPropertyType() {%n",
621605
VersionPropertyType.class.getName(),
622-
entityMeta.getEntityTypeName(),
623-
parentEntityTypeNameAsTypeParameter);
606+
entityMeta.getEntityTypeName(), Object.class.getName());
624607
iprint(" return %1$s;%n", versionName);
625608
iprint("}%n");
626609
print("%n");

src/main/java/org/seasar/doma/internal/apt/meta/EntityPropertyMeta.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ public class EntityPropertyMeta {
5555

5656
protected final String boxedClassName;
5757

58-
protected final boolean ownProperty;
59-
6058
protected final String fieldPrefix;
6159

6260
protected final ProcessingEnvironment env;
@@ -75,7 +73,7 @@ public class EntityPropertyMeta {
7573

7674
public EntityPropertyMeta(TypeElement entityElement,
7775
VariableElement propertyElement, NamingType namingType,
78-
boolean ownProperty, ProcessingEnvironment env) {
76+
ProcessingEnvironment env) {
7977
assertNotNull(entityElement, propertyElement, env);
8078
this.entityName = entityElement.getSimpleName().toString();
8179
this.entityTypeName = entityElement.getQualifiedName().toString();
@@ -85,7 +83,6 @@ public EntityPropertyMeta(TypeElement entityElement,
8583
this.typeName = TypeMirrorUtil.getTypeName(type, env);
8684
this.boxedTypeName = TypeMirrorUtil.getBoxedTypeName(type, env);
8785
this.boxedClassName = TypeMirrorUtil.getBoxedClassName(type, env);
88-
this.ownProperty = ownProperty;
8986
this.fieldPrefix = Options.getEntityFieldPrefix(env);
9087
this.env = env;
9188
}
@@ -154,10 +151,6 @@ public String getBoxedClassName() {
154151
return boxedClassName;
155152
}
156153

157-
public boolean isOwnProperty() {
158-
return ownProperty;
159-
}
160-
161154
public CtType getCtType() {
162155
return ctType;
163156
}
@@ -193,7 +186,7 @@ public boolean isEmbedded() {
193186
@Override
194187
public Boolean visitEmbeddableCtType(
195188
EmbeddableCtType ctType, Void p)
196-
throws RuntimeException {
189+
throws RuntimeException {
197190
return true;
198191
}
199192
}, null);

src/main/java/org/seasar/doma/internal/apt/meta/EntityPropertyMetaFactory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ public EntityPropertyMeta createEntityPropertyMeta(
7171
throw new AptIllegalStateException(fieldElement.toString());
7272
}
7373
EntityPropertyMeta propertyMeta = new EntityPropertyMeta(entityElement,
74-
fieldElement, entityMeta.getNamingType(),
75-
entityElement.equals(entityMeta.getEntityElement()), env);
74+
fieldElement, entityMeta.getNamingType(), env);
7675
doCtType(propertyMeta, fieldElement, entityMeta);
7776
doName(propertyMeta, fieldElement, entityMeta);
7877
doId(propertyMeta, fieldElement, entityMeta);

src/main/java/org/seasar/doma/jdbc/entity/DefaultPropertyType.java

Lines changed: 1 addition & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,6 @@ public class DefaultPropertyType<PARENT, ENTITY extends PARENT, BASIC, DOMAIN>
7070
/** ラッパーのサプライヤ */
7171
protected final Supplier<Wrapper<BASIC>> wrapperSupplier;
7272

73-
/** 親のエンティティのプロパティ型 */
74-
protected final EntityPropertyType<PARENT, BASIC> parentEntityPropertyType;
75-
7673
/** ドメインのメタタイプ */
7774
protected final DomainType<BASIC, DOMAIN> domainType;
7875

@@ -160,7 +157,6 @@ public DefaultPropertyType(Class<ENTITY> entityClass,
160157
this.entityPropertyClass = entityPropertyClass;
161158
this.basicClass = basicClass;
162159
this.wrapperSupplier = wrapperSupplier;
163-
this.parentEntityPropertyType = parentEntityPropertyType;
164160
this.domainType = domainType;
165161
this.name = name;
166162
int pos = name.lastIndexOf('.');
@@ -170,16 +166,12 @@ public DefaultPropertyType(Class<ENTITY> entityClass,
170166
this.insertable = insertable;
171167
this.updatable = updatable;
172168
this.quoteRequired = quoteRequired;
173-
this.field = parentEntityPropertyType == null ? new PropertyField<>(
174-
name, entityClass) : null;
169+
this.field = new PropertyField<>(name, entityClass);
175170
this.propertySupplier = createPropertySupplier();
176171
}
177172

178173
@SuppressWarnings("unchecked")
179174
private Supplier<Property<ENTITY, BASIC>> createPropertySupplier() {
180-
if (parentEntityPropertyType != null) {
181-
return () -> new ParentProperty();
182-
}
183175
if (domainType != null) {
184176
if (entityPropertyClass == Optional.class) {
185177
return () -> new DefaultProperty<Optional<DOMAIN>>(
@@ -328,51 +320,6 @@ protected <VALUE> ENTITY modifyIfNecessary(EntityType<ENTITY> entityType,
328320
}
329321
}
330322

331-
/**
332-
* @author nakamura-to
333-
*/
334-
protected class ParentProperty implements Property<ENTITY, BASIC> {
335-
336-
protected final Property<PARENT, BASIC> delegate;
337-
338-
protected ParentProperty() {
339-
this.delegate = parentEntityPropertyType.createProperty();
340-
}
341-
342-
@Override
343-
public Object get() {
344-
return delegate.get();
345-
}
346-
347-
@Override
348-
public Property<ENTITY, BASIC> load(ENTITY entity) {
349-
delegate.load(entity);
350-
return this;
351-
}
352-
353-
@Override
354-
public Property<ENTITY, BASIC> save(ENTITY entity) {
355-
delegate.save(entity);
356-
return this;
357-
}
358-
359-
@Override
360-
public InParameter<BASIC> asInParameter() {
361-
return delegate.asInParameter();
362-
}
363-
364-
@Override
365-
public Wrapper<BASIC> getWrapper() {
366-
return delegate.getWrapper();
367-
}
368-
369-
@Override
370-
public Optional<Class<?>> getDomainClass() {
371-
return delegate.getDomainClass();
372-
}
373-
374-
}
375-
376323
/**
377324
* @author nakamura-to
378325
*/

src/test/resources/org/seasar/doma/internal/apt/entity/EntityProcessorTest_Extends.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public final class _ChildEntity extends org.seasar.doma.jdbc.entity.AbstractEnti
1313
private final org.seasar.doma.jdbc.entity.NamingType __namingType = null;
1414

1515
/** the aaa */
16-
public final org.seasar.doma.jdbc.entity.DefaultPropertyType<org.seasar.doma.internal.apt.entity.ParentEntity, org.seasar.doma.internal.apt.entity.ChildEntity, java.lang.Integer, Object> $aaa = new org.seasar.doma.jdbc.entity.DefaultPropertyType<>(org.seasar.doma.internal.apt.entity.ChildEntity.class, java.lang.Integer.class, java.lang.Integer.class, () -> new org.seasar.doma.wrapper.IntegerWrapper(), org.seasar.doma.internal.apt.entity._ParentEntity.getSingletonInternal().$aaa, null, "aaa", "", __namingType, true, true, false);
16+
public final org.seasar.doma.jdbc.entity.DefaultPropertyType<java.lang.Object, org.seasar.doma.internal.apt.entity.ChildEntity, java.lang.Integer, Object> $aaa = new org.seasar.doma.jdbc.entity.DefaultPropertyType<>(org.seasar.doma.internal.apt.entity.ChildEntity.class, java.lang.Integer.class, java.lang.Integer.class, () -> new org.seasar.doma.wrapper.IntegerWrapper(), null, null, "aaa", "", __namingType, true, true, false);
1717

1818
/** the bbb */
1919
public final org.seasar.doma.jdbc.entity.DefaultPropertyType<java.lang.Object, org.seasar.doma.internal.apt.entity.ChildEntity, java.math.BigDecimal, Object> $bbb = new org.seasar.doma.jdbc.entity.DefaultPropertyType<>(org.seasar.doma.internal.apt.entity.ChildEntity.class, java.math.BigDecimal.class, java.math.BigDecimal.class, () -> new org.seasar.doma.wrapper.BigDecimalWrapper(), null, null, "bbb", "", __namingType, true, true, false);

src/test/resources/org/seasar/doma/internal/apt/entity/EntityProcessorTest_ExtendsListenerInherited.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public final class _Child2InheritingEntity extends org.seasar.doma.jdbc.entity.A
1313
private final org.seasar.doma.jdbc.entity.NamingType __namingType = null;
1414

1515
/** the aaa */
16-
public final org.seasar.doma.jdbc.entity.DefaultPropertyType<org.seasar.doma.internal.apt.entity.Parent2Entity, org.seasar.doma.internal.apt.entity.Child2InheritingEntity, java.lang.Integer, Object> $aaa = new org.seasar.doma.jdbc.entity.DefaultPropertyType<>(org.seasar.doma.internal.apt.entity.Child2InheritingEntity.class, java.lang.Integer.class, java.lang.Integer.class, () -> new org.seasar.doma.wrapper.IntegerWrapper(), org.seasar.doma.internal.apt.entity._Parent2Entity.getSingletonInternal().$aaa, null, "aaa", "", __namingType, true, true, false);
16+
public final org.seasar.doma.jdbc.entity.DefaultPropertyType<java.lang.Object, org.seasar.doma.internal.apt.entity.Child2InheritingEntity, java.lang.Integer, Object> $aaa = new org.seasar.doma.jdbc.entity.DefaultPropertyType<>(org.seasar.doma.internal.apt.entity.Child2InheritingEntity.class, java.lang.Integer.class, java.lang.Integer.class, () -> new org.seasar.doma.wrapper.IntegerWrapper(), null, null, "aaa", "", __namingType, true, true, false);
1717

1818
/** the bbb */
1919
public final org.seasar.doma.jdbc.entity.DefaultPropertyType<java.lang.Object, org.seasar.doma.internal.apt.entity.Child2InheritingEntity, java.math.BigDecimal, Object> $bbb = new org.seasar.doma.jdbc.entity.DefaultPropertyType<>(org.seasar.doma.internal.apt.entity.Child2InheritingEntity.class, java.math.BigDecimal.class, java.math.BigDecimal.class, () -> new org.seasar.doma.wrapper.BigDecimalWrapper(), null, null, "bbb", "", __namingType, true, true, false);

0 commit comments

Comments
 (0)