Skip to content

Commit 81d9766

Browse files
authored
Merge pull request #203 from domaframework/tenant-id
Add `@TenantId` to support the partitioned approach of multi-tenancy
2 parents ad80cb2 + bc79170 commit 81d9766

File tree

77 files changed

+1437
-123
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+1437
-123
lines changed

docs/sources/entity.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,22 @@ RDBMSによってはサポートされていません。
281281

282282
フィールドの型が :doc:`embeddable` の場合、 ``@Version`` は指定できません。
283283

284+
285+
テナント識別子
286+
------------------------------
287+
288+
テナント識別子は ``@TenantId`` を注釈して示します。
289+
テナント識別子を注釈すると、更新や削除などSQLが生成されるタイプのクエリにおいて対応するカラムが検索条件としてWHERE句に含まれます。
290+
291+
.. code-block:: java
292+
293+
@TenantId
294+
String tenantId;
295+
296+
.. note::
297+
298+
フィールドの型が :doc:`embeddable` の場合、 ``@TenantId`` は指定できません。
299+
284300
非永続的なフィールド
285301
--------------------------------
286302

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2004-2010 the Seasar Foundation and the Others.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific language
14+
* governing permissions and limitations under the License.
15+
*/
16+
package org.seasar.doma;
17+
18+
import java.lang.annotation.ElementType;
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
21+
import java.lang.annotation.Target;
22+
23+
/**
24+
* テナントの識別子を示します。
25+
* <p>
26+
* このアノテーションが注釈されるフィールドは、エンティティインタフェースのメンバでなければいけません。
27+
* <p>
28+
* SQLが生成されるタイプのクエリにおいて、注釈されたフィールドにマップされたカラムは検索条件としてWHERE句に含まれます。
29+
*
30+
* <h3>例:</h3>
31+
*
32+
* <pre>
33+
* &#064;Entity
34+
* public class Employee {
35+
* ...
36+
*
37+
* &#064;TenantId
38+
* String tenantId;
39+
* }
40+
* </pre>
41+
*
42+
* @author nakamura
43+
*/
44+
@Target(ElementType.FIELD)
45+
@Retention(RetentionPolicy.RUNTIME)
46+
@EntityField
47+
public @interface TenantId {
48+
}

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

Lines changed: 81 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.seasar.doma.jdbc.entity.PreInsertContext;
6161
import org.seasar.doma.jdbc.entity.PreUpdateContext;
6262
import org.seasar.doma.jdbc.entity.Property;
63+
import org.seasar.doma.jdbc.entity.TenantIdPropertyType;
6364
import org.seasar.doma.jdbc.entity.VersionPropertyType;
6465

6566
/**
@@ -193,67 +194,77 @@ protected void printPropertyTypeFields() {
193194
if (pm.isId()) {
194195
if (pm.getIdGeneratorMeta() != null) {
195196
iprint("public final %1$s<%11$s, %2$s, %3$s, %14$s> %12$s = new %1$s<>(%6$s.class, %13$s.class, %3$s.class, () -> %7$s, %10$s, %8$s, \"%4$s\", \"%5$s\", __namingType, %15$s, __idGenerator);%n",
196-
/* 1 */GeneratedIdPropertyType.class.getName(),
197-
/* 2 */entityMeta.getEntityTypeName(),
198-
/* 3 */basicCtType.getBoxedTypeName(),
199-
/* 4 */pm.getName(), /* 5 */pm.getColumnName(),
200-
/* 6 */entityMeta.getEntityTypeName(),
201-
/* 7 */newWrapperExpr, /* 8 */domainType,
202-
/* 9 */pm.getBoxedTypeName(),
203-
/* 10 */NULL,
204-
/* 11 */Object.class.getName(),
205-
/* 12 */pm.getFieldName(),
206-
/* 13 */pm.getBoxedClassName(),
207-
/* 14 */domainTypeName,
208-
/* 15 */pm.isColumnQuoteRequired());
197+
/* 1 */GeneratedIdPropertyType.class.getName(),
198+
/* 2 */entityMeta.getEntityTypeName(),
199+
/* 3 */basicCtType.getBoxedTypeName(),
200+
/* 4 */pm.getName(), /* 5 */pm.getColumnName(),
201+
/* 6 */entityMeta.getEntityTypeName(),
202+
/* 7 */newWrapperExpr, /* 8 */domainType,
203+
/* 9 */pm.getBoxedTypeName(), /* 10 */NULL,
204+
/* 11 */Object.class.getName(),
205+
/* 12 */pm.getFieldName(),
206+
/* 13 */pm.getBoxedClassName(),
207+
/* 14 */domainTypeName,
208+
/* 15 */pm.isColumnQuoteRequired());
209209
} else {
210210
iprint("public final %1$s<%11$s, %2$s, %3$s, %14$s> %12$s = new %1$s<>(%6$s.class, %13$s.class, %3$s.class, () -> %7$s, %10$s, %8$s, \"%4$s\", \"%5$s\", __namingType, %15$s);%n",
211-
/* 1 */AssignedIdPropertyType.class.getName(),
212-
/* 2 */entityMeta.getEntityTypeName(),
213-
/* 3 */basicCtType.getBoxedTypeName(),
214-
/* 4 */pm.getName(), /* 5 */pm.getColumnName(),
215-
/* 6 */entityMeta.getEntityTypeName(),
216-
/* 7 */newWrapperExpr, /* 8 */domainType,
217-
/* 9 */pm.getBoxedTypeName(),
218-
/* 10 */NULL,
219-
/* 11 */Object.class.getName(),
220-
/* 12 */pm.getFieldName(),
221-
/* 13 */pm.getBoxedClassName(),
222-
/* 14 */domainTypeName,
223-
/* 15 */pm.isColumnQuoteRequired());
211+
/* 1 */AssignedIdPropertyType.class.getName(),
212+
/* 2 */entityMeta.getEntityTypeName(),
213+
/* 3 */basicCtType.getBoxedTypeName(),
214+
/* 4 */pm.getName(), /* 5 */pm.getColumnName(),
215+
/* 6 */entityMeta.getEntityTypeName(),
216+
/* 7 */newWrapperExpr, /* 8 */domainType,
217+
/* 9 */pm.getBoxedTypeName(), /* 10 */NULL,
218+
/* 11 */Object.class.getName(),
219+
/* 12 */pm.getFieldName(),
220+
/* 13 */pm.getBoxedClassName(),
221+
/* 14 */domainTypeName,
222+
/* 15 */pm.isColumnQuoteRequired());
224223
}
225224
} else if (pm.isVersion()) {
226225
iprint("public final %1$s<%11$s, %2$s, %3$s, %14$s> %12$s = new %1$s<>(%6$s.class, %13$s.class, %3$s.class, () -> %7$s, %10$s, %8$s, \"%4$s\", \"%5$s\", __namingType, %15$s);%n",
227-
/* 1 */VersionPropertyType.class.getName(),
228-
/* 2 */entityMeta.getEntityTypeName(),
229-
/* 3 */basicCtType.getBoxedTypeName(),
230-
/* 4 */pm.getName(), /* 5 */pm.getColumnName(),
231-
/* 6 */entityMeta.getEntityTypeName(),
232-
/* 7 */newWrapperExpr, /* 8 */domainType,
233-
/* 9 */pm.getBoxedTypeName(),
234-
/* 10 */NULL,
235-
/* 11 */Object.class.getName(),
236-
/* 12 */pm.getFieldName(),
237-
/* 13 */pm.getBoxedClassName(),
238-
/* 14 */domainTypeName,
239-
/* 15 */pm.isColumnQuoteRequired());
226+
/* 1 */VersionPropertyType.class.getName(),
227+
/* 2 */entityMeta.getEntityTypeName(),
228+
/* 3 */basicCtType.getBoxedTypeName(),
229+
/* 4 */pm.getName(), /* 5 */pm.getColumnName(),
230+
/* 6 */entityMeta.getEntityTypeName(),
231+
/* 7 */newWrapperExpr, /* 8 */domainType,
232+
/* 9 */pm.getBoxedTypeName(), /* 10 */NULL,
233+
/* 11 */Object.class.getName(),
234+
/* 12 */pm.getFieldName(),
235+
/* 13 */pm.getBoxedClassName(),
236+
/* 14 */domainTypeName,
237+
/* 15 */pm.isColumnQuoteRequired());
238+
} else if (pm.isTenantId()) {
239+
iprint("public final %1$s<%11$s, %2$s, %3$s, %14$s> %12$s = new %1$s<>(%6$s.class, %13$s.class, %3$s.class, () -> %7$s, %10$s, %8$s, \"%4$s\", \"%5$s\", __namingType, %15$s);%n",
240+
/* 1 */TenantIdPropertyType.class.getName(),
241+
/* 2 */entityMeta.getEntityTypeName(),
242+
/* 3 */basicCtType.getBoxedTypeName(),
243+
/* 4 */pm.getName(), /* 5 */pm.getColumnName(),
244+
/* 6 */entityMeta.getEntityTypeName(),
245+
/* 7 */newWrapperExpr, /* 8 */domainType,
246+
/* 9 */pm.getBoxedTypeName(), /* 10 */NULL,
247+
/* 11 */Object.class.getName(),
248+
/* 12 */pm.getFieldName(),
249+
/* 13 */pm.getBoxedClassName(),
250+
/* 14 */domainTypeName,
251+
/* 15 */pm.isColumnQuoteRequired());
240252
} else {
241253
iprint("public final %1$s<%13$s, %2$s, %3$s, %16$s> %14$s = new %1$s<>(%8$s.class, %15$s.class, %3$s.class, () -> %9$s, %12$s, %10$s, \"%4$s\", \"%5$s\", __namingType, %6$s, %7$s, %17$s);%n",
242-
/* 1 */DefaultPropertyType.class.getName(),
243-
/* 2 */entityMeta.getEntityTypeName(),
244-
/* 3 */basicCtType.getBoxedTypeName(),
245-
/* 4 */pm.getName(), /* 5 */pm.getColumnName(),
246-
/* 6 */pm.isColumnInsertable(),
247-
/* 7 */pm.isColumnUpdatable(),
248-
/* 8 */entityMeta.getEntityTypeName(),
249-
/* 9 */newWrapperExpr, /* 10 */domainType,
250-
/* 11 */pm.getBoxedTypeName(),
251-
/* 12 */NULL,
252-
/* 13 */Object.class.getName(),
253-
/* 14 */pm.getFieldName(),
254-
/* 15 */pm.getBoxedClassName(),
255-
/* 16 */domainTypeName,
256-
/* 17 */pm.isColumnQuoteRequired());
254+
/* 1 */DefaultPropertyType.class.getName(),
255+
/* 2 */entityMeta.getEntityTypeName(),
256+
/* 3 */basicCtType.getBoxedTypeName(),
257+
/* 4 */pm.getName(), /* 5 */pm.getColumnName(),
258+
/* 6 */pm.isColumnInsertable(),
259+
/* 7 */pm.isColumnUpdatable(),
260+
/* 8 */entityMeta.getEntityTypeName(),
261+
/* 9 */newWrapperExpr, /* 10 */domainType,
262+
/* 11 */pm.getBoxedTypeName(), /* 12 */NULL,
263+
/* 13 */Object.class.getName(),
264+
/* 14 */pm.getFieldName(),
265+
/* 15 */pm.getBoxedClassName(),
266+
/* 16 */domainTypeName,
267+
/* 17 */pm.isColumnQuoteRequired());
257268
}
258269
}
259270
print("%n");
@@ -403,6 +414,7 @@ protected void printMethods() {
403414
printGetIdPropertyTypesMethod();
404415
printGetGeneratedIdPropertyTypeMethod();
405416
printGetVersionPropertyTypeMethod();
417+
printGetTenantIdPropertyTypeMethod();
406418
printNewEntityMethod();
407419
printGetEntityClassMethod();
408420
printGetOriginalStatesMethod();
@@ -609,6 +621,21 @@ protected void printGetVersionPropertyTypeMethod() {
609621
print("%n");
610622
}
611623

624+
protected void printGetTenantIdPropertyTypeMethod() {
625+
String tenantIdName = "null";
626+
if (entityMeta.hasTenantIdPropertyMeta()) {
627+
EntityPropertyMeta pm = entityMeta.getTenanatIdPropertyMeta();
628+
tenantIdName = pm.getFieldName();
629+
}
630+
iprint("@Override%n");
631+
iprint("public %1$s<%3$s, %2$s, ?, ?> getTenantIdPropertyType() {%n",
632+
TenantIdPropertyType.class.getName(),
633+
entityMeta.getEntityTypeName(), Object.class.getName());
634+
iprint(" return %1$s;%n", tenantIdName);
635+
iprint("}%n");
636+
print("%n");
637+
}
638+
612639
protected void printNewEntityMethod() {
613640
if (hasGenericTypeProperty()) {
614641
iprint("@SuppressWarnings(\"unchecked\")%n");

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.seasar.doma.Id;
4848
import org.seasar.doma.OriginalStates;
4949
import org.seasar.doma.ParameterName;
50+
import org.seasar.doma.TenantId;
5051
import org.seasar.doma.Transient;
5152
import org.seasar.doma.Version;
5253
import org.seasar.doma.internal.Constants;
@@ -208,6 +209,11 @@ public void doFieldElements(TypeElement embeddableElement,
208209
fieldElement, new Object[] {
209210
embeddableElement.getQualifiedName(),
210211
fieldElement.getSimpleName() });
212+
} else if (fieldElement.getAnnotation(TenantId.class) != null) {
213+
throw new AptException(Message.DOMA4443, env,
214+
fieldElement, new Object[] {
215+
embeddableElement.getQualifiedName(),
216+
fieldElement.getSimpleName() });
211217
} else if (fieldElement.getAnnotation(GeneratedValue.class) != null) {
212218
throw new AptException(Message.DOMA4291, env,
213219
fieldElement, new Object[] {

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public class EntityMeta implements TypeElementMeta {
6060

6161
protected EntityPropertyMeta versionPropertyMeta;
6262

63+
protected EntityPropertyMeta tenantIdPropertyMeta;
64+
6365
protected EntityPropertyMeta generatedIdPropertyMeta;
6466

6567
protected String entityName;
@@ -127,6 +129,9 @@ public void addPropertyMeta(EntityPropertyMeta propertyMeta) {
127129
if (propertyMeta.isVersion()) {
128130
versionPropertyMeta = propertyMeta;
129131
}
132+
if (propertyMeta.isTenantId()) {
133+
tenantIdPropertyMeta = propertyMeta;
134+
}
130135
}
131136

132137
public List<EntityPropertyMeta> getAllPropertyMetas() {
@@ -148,6 +153,14 @@ public EntityPropertyMeta getVersionPropertyMeta() {
148153
return versionPropertyMeta;
149154
}
150155

156+
public boolean hasTenantIdPropertyMeta() {
157+
return tenantIdPropertyMeta != null;
158+
}
159+
160+
public EntityPropertyMeta getTenanatIdPropertyMeta() {
161+
return tenantIdPropertyMeta;
162+
}
163+
151164
public boolean hasGeneratedIdPropertyMeta() {
152165
return generatedIdPropertyMeta != null;
153166
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public class EntityPropertyMeta {
6565

6666
protected boolean version;
6767

68+
protected boolean tenantId;
69+
6870
protected ColumnMirror columnMirror;
6971

7072
protected IdGeneratorMeta idGeneratorMeta;
@@ -127,6 +129,14 @@ public void setVersion(boolean version) {
127129
this.version = version;
128130
}
129131

132+
public boolean isTenantId() {
133+
return tenantId;
134+
}
135+
136+
public void setTenantId(boolean tenantId) {
137+
this.tenantId = tenantId;
138+
}
139+
130140
public IdGeneratorMeta getIdGeneratorMeta() {
131141
return idGeneratorMeta;
132142
}

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.seasar.doma.Id;
3030
import org.seasar.doma.SequenceGenerator;
3131
import org.seasar.doma.TableGenerator;
32+
import org.seasar.doma.TenantId;
3233
import org.seasar.doma.Version;
3334
import org.seasar.doma.internal.apt.AptException;
3435
import org.seasar.doma.internal.apt.AptIllegalStateException;
@@ -76,6 +77,7 @@ public EntityPropertyMeta createEntityPropertyMeta(
7677
doName(propertyMeta, fieldElement, entityMeta);
7778
doId(propertyMeta, fieldElement, entityMeta);
7879
doVersion(propertyMeta, fieldElement, entityMeta);
80+
doTenantId(propertyMeta, fieldElement, entityMeta);
7981
doColumn(propertyMeta, fieldElement, entityMeta);
8082
return propertyMeta;
8183
}
@@ -387,6 +389,28 @@ protected void doVersion(EntityPropertyMeta propertyMeta,
387389
}
388390
}
389391

392+
protected void doTenantId(EntityPropertyMeta propertyMeta,
393+
VariableElement fieldElement, EntityMeta entityMeta) {
394+
TenantId tenantId = fieldElement.getAnnotation(TenantId.class);
395+
if (tenantId != null) {
396+
if (propertyMeta.isEmbedded()) {
397+
throw new AptException(Message.DOMA4441, env, fieldElement,
398+
new Object[] {
399+
entityMeta.getEntityElement()
400+
.getQualifiedName(),
401+
fieldElement.getSimpleName() });
402+
}
403+
if (entityMeta.hasTenantIdPropertyMeta()) {
404+
throw new AptException(Message.DOMA4442, env, fieldElement,
405+
new Object[] {
406+
entityMeta.getEntityElement()
407+
.getQualifiedName(),
408+
fieldElement.getSimpleName() });
409+
}
410+
propertyMeta.setTenantId(true);
411+
}
412+
}
413+
390414
protected void doColumn(EntityPropertyMeta propertyMeta,
391415
VariableElement fieldElement, EntityMeta entityMeta) {
392416
ColumnMirror columnMirror = ColumnMirror.newInstance(fieldElement, env);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,11 @@ public boolean isVersion() {
260260
return false;
261261
}
262262

263+
@Override
264+
public boolean isTenantId() {
265+
return false;
266+
}
267+
263268
@Override
264269
public boolean isInsertable() {
265270
return insertable;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ String getColumnName(BiFunction<NamingType, String, String> namingFunction,
109109
*/
110110
boolean isVersion();
111111

112+
boolean isTenantId();
113+
112114
/**
113115
* 挿入可能かどうかを返します。
114116
*

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ String getQualifiedTableName(
150150
*/
151151
VersionPropertyType<? super ENTITY, ENTITY, ?, ?> getVersionPropertyType();
152152

153+
TenantIdPropertyType<? super ENTITY, ENTITY, ?, ?> getTenantIdPropertyType();
154+
153155
/**
154156
* 識別子のプロパティ型のリストを返します。
155157
*

0 commit comments

Comments
 (0)