Skip to content

Commit 8fc3c6a

Browse files
committed
Add support for the @Returning annotation in multi-row insert DAO operations
1 parent 997dcd5 commit 8fc3c6a

File tree

16 files changed

+369
-29
lines changed

16 files changed

+369
-29
lines changed

doma-core/src/main/java/org/seasar/doma/MultiInsert.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,10 @@
116116
* @return the keys that should be used to determine if a duplicate key exists.
117117
*/
118118
String[] duplicateKeys() default {};
119+
120+
/**
121+
* @return the {@link Returning} annotation configuration, which defines inclusions or exclusions
122+
* for returning values.
123+
*/
124+
Returning returning() default @Returning;
119125
}

doma-core/src/main/java/org/seasar/doma/message/Message.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,8 @@ public enum Message implements MessageResource {
10111011
DOMA4494("The property \"{0}\" is not found in the entity class \"{1}\"."),
10121012
DOMA4495(
10131013
"When \"returning = @Returning\" is specified, the return type must be the same as the parameter type or an Optional whose element is the parameter type."),
1014+
DOMA4496(
1015+
"When \"returning = @Returning\" is specified, the return type must be a List of the entity class \"{0}\"."),
10141016

10151017
// other
10161018
DOMA5001(

doma-processor/src/main/java/org/seasar/doma/internal/apt/annot/Annotations.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,15 @@ public InsertAnnot newInsertAnnot(ExecutableElement method) {
260260

261261
public MultiInsertAnnot newMultiInsertAnnot(ExecutableElement method) {
262262
assertNotNull(method);
263-
return newInstance(method, MultiInsert.class, MultiInsertAnnot::new);
263+
AnnotationMirror multiInsertMirror =
264+
ctx.getMoreElements().getAnnotationMirror(method, MultiInsert.class);
265+
if (multiInsertMirror == null) {
266+
return null;
267+
}
268+
ReturningAnnot returningAnnot = newReturningAnnot(multiInsertMirror, ModifyAnnot.RETURNING);
269+
Map<String, AnnotationValue> valuesWithDefaults =
270+
ctx.getMoreElements().getValuesWithDefaults(multiInsertMirror);
271+
return new MultiInsertAnnot(multiInsertMirror, returningAnnot, valuesWithDefaults);
264272
}
265273

266274
public MetamodelAnnot newMetamodelAnnot(AnnotationMirror annotationMirror) {

doma-processor/src/main/java/org/seasar/doma/internal/apt/annot/MultiInsertAnnot.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,27 +31,23 @@ public class MultiInsertAnnot extends AbstractAnnot {
3131

3232
private static final String QUERY_TIMEOUT = "queryTimeout";
3333
private static final String INCLUDE = "include";
34-
3534
private static final String EXCLUDE = "exclude";
36-
3735
private static final String SQL_LOG = "sqlLog";
38-
3936
private static final String DUPLICATE_KEY_TYPE = "duplicateKeyType";
40-
4137
private static final String DUPLICATE_KEYS = "duplicateKeys";
4238

4339
private final AnnotationValue queryTimeout;
4440
private final AnnotationValue include;
45-
4641
private final AnnotationValue exclude;
47-
4842
private final AnnotationValue sqlLog;
49-
5043
private final AnnotationValue duplicateKeyType;
51-
5244
private final AnnotationValue duplicateKeys;
45+
private final ReturningAnnot returningAnnot;
5346

54-
MultiInsertAnnot(AnnotationMirror annotationMirror, Map<String, AnnotationValue> values) {
47+
MultiInsertAnnot(
48+
AnnotationMirror annotationMirror,
49+
ReturningAnnot returningAnnot,
50+
Map<String, AnnotationValue> values) {
5551
super(annotationMirror);
5652

5753
// non null values
@@ -63,6 +59,7 @@ public class MultiInsertAnnot extends AbstractAnnot {
6359
this.exclude = values.get(EXCLUDE);
6460
this.duplicateKeyType = values.get(DUPLICATE_KEY_TYPE);
6561
this.duplicateKeys = values.get(DUPLICATE_KEYS);
62+
this.returningAnnot = returningAnnot;
6663
}
6764

6865
public AnnotationValue getQueryTimeout() {
@@ -85,6 +82,10 @@ public AnnotationValue getSqlLog() {
8582
return sqlLog;
8683
}
8784

85+
public ReturningAnnot getReturningAnnot() {
86+
return returningAnnot;
87+
}
88+
8889
public int getQueryTimeoutValue() {
8990
Integer value = AnnotationValueUtil.toInteger(queryTimeout);
9091
if (value == null) {

doma-processor/src/main/java/org/seasar/doma/internal/apt/generator/DaoImplQueryMethodGenerator.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -656,20 +656,43 @@ public Void visitAutoMultiInsertQueryMeta(AutoMultiInsertQueryMeta m) {
656656
iprint("__query.setDuplicateKeyNames(%1$s);%n", toConstants(duplicateKeys));
657657
}
658658

659+
ReturningAnnot returningAnnot = m.getReturningAnnot();
660+
if (returningAnnot != null) {
661+
iprint(
662+
"__query.setReturning(new %1$s(%2$s.of(%3$s), %2$s.of(%4$s)));%n",
663+
/* 1 */ ReturningProperties.SpecificNames.class.getName().replace('$', '.'),
664+
/* 2 */ List.class,
665+
/* 3 */ toConstants(returningAnnot.getIncludeValue()),
666+
/* 4 */ toConstants(returningAnnot.getExcludeValue()));
667+
}
668+
659669
iprint("__query.prepare();%n");
660-
iprint(
661-
"%1$s __command = __support.getCommandImplementors().create%2$s(%3$s, __query);%n",
662-
m.getCommandClass().getName(), m.getCommandClass().getSimpleName(), methodName);
663670

664-
EntityCtType entityCtType = m.getEntityCtType();
665-
if (entityCtType != null && entityCtType.isImmutable()) {
666-
iprint("int __count = __command.execute();%n");
667-
iprint("__query.complete();%n");
671+
if (returningAnnot == null) {
668672
iprint(
669-
"%1$s __result = new %1$s(__count, __query.getEntities());%n",
670-
m.getReturnMeta().getType());
673+
"%1$s __command = __support.getCommandImplementors().create%2$s(%3$s, __query);%n",
674+
m.getCommandClass().getName(), m.getCommandClass().getSimpleName(), methodName);
675+
676+
EntityCtType entityCtType = m.getEntityCtType();
677+
if (entityCtType != null && entityCtType.isImmutable()) {
678+
iprint("int __count = __command.execute();%n");
679+
iprint("__query.complete();%n");
680+
iprint(
681+
"%1$s __result = new %1$s(__count, __query.getEntities());%n",
682+
m.getReturnMeta().getType());
683+
} else {
684+
iprint("%1$s __result = __command.execute();%n", m.getReturnMeta().getType());
685+
iprint("__query.complete();%n");
686+
}
671687
} else {
672-
iprint("%1$s __result = __command.execute();%n", m.getReturnMeta().getType());
688+
iprint(
689+
"var __command = __support.getCommandImplementors().create%1$s(%2$s, __query, new %3$s<>(%4$s), %5$s);%n",
690+
/* 1 */ m.getCommandClass().getSimpleName(),
691+
/* 2 */ methodName,
692+
/* 3 */ EntityResultListHandler.class,
693+
/* 4 */ m.getEntityCtType().getTypeCode(),
694+
/* 5 */ "java.util.Collections::emptyList");
695+
iprint("var __result = __command.execute();%n");
673696
iprint("__query.complete();%n");
674697
}
675698

doma-processor/src/main/java/org/seasar/doma/internal/apt/meta/query/AutoModifyQueryMetaFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ protected void doReturnType(AutoModifyQueryMeta queryMeta) {
9090
}
9191
}
9292
} else {
93-
if (!returnMeta.isEntity(entityCtType) && !returnMeta.isOptionalEntity(entityCtType)) {
93+
if (!returnMeta.isEntity(entityCtType) && !returnMeta.isEntityOptional(entityCtType)) {
9494
throw new AptException(Message.DOMA4495, methodElement, new Object[] {});
9595
}
9696
}

doma-processor/src/main/java/org/seasar/doma/internal/apt/meta/query/AutoMultiInsertQueryMeta.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
import javax.lang.model.element.ExecutableElement;
2020
import javax.lang.model.element.TypeElement;
2121
import org.seasar.doma.internal.apt.annot.MultiInsertAnnot;
22+
import org.seasar.doma.internal.apt.annot.ReturningAnnot;
2223
import org.seasar.doma.internal.apt.cttype.EntityCtType;
2324
import org.seasar.doma.jdbc.SqlLogType;
25+
import org.seasar.doma.jdbc.command.InsertReturningCommand;
2426
import org.seasar.doma.jdbc.query.DuplicateKeyType;
2527

2628
public class AutoMultiInsertQueryMeta extends AbstractQueryMeta {
@@ -59,6 +61,10 @@ void setMultiInsertAnnot(MultiInsertAnnot multiInsertAnnot) {
5961
this.multiInsertAnnot = multiInsertAnnot;
6062
}
6163

64+
public ReturningAnnot getReturningAnnot() {
65+
return multiInsertAnnot.getReturningAnnot();
66+
}
67+
6268
public int getQueryTimeout() {
6369
return multiInsertAnnot.getQueryTimeoutValue();
6470
}
@@ -83,6 +89,15 @@ public DuplicateKeyType getDuplicateKeyType() {
8389
return multiInsertAnnot.getDuplicateKeyTypeValue();
8490
}
8591

92+
@Override
93+
public Class<?> getCommandClass() {
94+
var returningAnnot = multiInsertAnnot.getReturningAnnot();
95+
if (returningAnnot == null) {
96+
return super.getCommandClass();
97+
}
98+
return InsertReturningCommand.class;
99+
}
100+
86101
@Override
87102
public <R> R accept(QueryMetaVisitor<R> visitor) {
88103
return visitor.visitAutoMultiInsertQueryMeta(this);

doma-processor/src/main/java/org/seasar/doma/internal/apt/meta/query/AutoMultiInsertQueryMetaFactory.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import javax.lang.model.element.ExecutableElement;
2020
import javax.lang.model.element.TypeElement;
2121
import javax.lang.model.element.VariableElement;
22+
import javax.lang.model.type.TypeMirror;
2223
import org.seasar.doma.internal.apt.AptException;
2324
import org.seasar.doma.internal.apt.RoundContext;
2425
import org.seasar.doma.internal.apt.annot.MultiInsertAnnot;
@@ -64,13 +65,22 @@ private AutoMultiInsertQueryMeta createAutoMultiInsertQueryMeta() {
6465
protected void doReturnType(AutoMultiInsertQueryMeta queryMeta) {
6566
QueryReturnMeta returnMeta = createReturnMeta(queryMeta);
6667
EntityCtType entityCtType = queryMeta.getEntityCtType();
67-
if (entityCtType != null && entityCtType.isImmutable()) {
68-
if (!returnMeta.isMultiResult(entityCtType)) {
69-
throw new AptException(Message.DOMA4461, methodElement, new Object[] {});
68+
if (queryMeta.getReturningAnnot() == null) {
69+
if (entityCtType != null && entityCtType.isImmutable()) {
70+
if (!returnMeta.isMultiResult(entityCtType)) {
71+
throw new AptException(Message.DOMA4461, methodElement, new Object[] {});
72+
}
73+
} else {
74+
if (!returnMeta.isPrimitiveInt()) {
75+
throw new AptException(Message.DOMA4001, methodElement, new Object[] {});
76+
}
7077
}
7178
} else {
72-
if (!returnMeta.isPrimitiveInt()) {
73-
throw new AptException(Message.DOMA4001, methodElement, new Object[] {});
79+
TypeElement listElement = ctx.getMoreElements().getTypeElement(List.class);
80+
TypeMirror listType = ctx.getMoreTypes().getDeclaredType(listElement, entityCtType.getType());
81+
if (!ctx.getMoreTypes().isSameType(returnMeta.getType(), listType)) {
82+
throw new AptException(
83+
Message.DOMA4496, methodElement, new Object[] {entityCtType.getQualifiedName()});
7484
}
7585
}
7686
queryMeta.setReturnMeta(returnMeta);
@@ -135,5 +145,12 @@ public EntityCtType visitEntityCtType(EntityCtType ctType, Void p)
135145
insertAnnot.getInclude(),
136146
insertAnnot.getExclude(),
137147
insertAnnot.getDuplicateKeys());
148+
149+
var returningAnnot = queryMeta.getReturningAnnot();
150+
if (returningAnnot != null) {
151+
var returningAnnotValidator =
152+
new ReturningAnnotValidator(ctx, entityCtType.getType(), methodElement, returningAnnot);
153+
returningAnnotValidator.validate();
154+
}
138155
}
139156
}

doma-processor/src/main/java/org/seasar/doma/internal/apt/meta/query/QueryReturnMeta.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public boolean isEntity(EntityCtType entityCtType) {
130130
return ctType.isSameType(entityCtType);
131131
}
132132

133-
public boolean isOptionalEntity(EntityCtType entityCtType) {
133+
public boolean isEntityOptional(EntityCtType entityCtType) {
134134
return ctType.accept(
135135
new SimpleCtTypeVisitor<Boolean, Void, RuntimeException>(false) {
136136
@Override

doma-processor/src/test/java/org/seasar/doma/internal/apt/processor/dao/DaoProcessorTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContex
174174
invocationContext(MultipleAnnotateWithDao.class),
175175
invocationContext(IgnoreGeneratedKeysDao.class),
176176
invocationContext(AutoMultiInsertDao.class),
177-
invocationContext(ReturningDao.class));
177+
invocationContext(ReturningDao.class),
178+
invocationContext(MultiInsertReturningDao.class));
178179
}
179180

180181
private TestTemplateInvocationContext invocationContext(Class<?> clazz, String... options) {
@@ -272,7 +273,10 @@ public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContex
272273
invocationContext(ReturningDao_IllegalSqlAnnotation.class, Message.DOMA4492),
273274
invocationContext(ReturningDao_IllegalInclude.class, Message.DOMA4493),
274275
invocationContext(ReturningDao_IllegalExclude.class, Message.DOMA4494),
275-
invocationContext(ReturningDao_IllegalReturnType.class, Message.DOMA4495));
276+
invocationContext(ReturningDao_IllegalReturnType.class, Message.DOMA4495),
277+
invocationContext(MultiInsertReturningDao_IllegalInclude.class, Message.DOMA4493),
278+
invocationContext(MultiInsertReturningDao_IllegalExclude.class, Message.DOMA4494),
279+
invocationContext(MultiInsertReturningDao_IllegalReturnType.class, Message.DOMA4496));
276280
}
277281

278282
private TestTemplateInvocationContext invocationContext(Class<?> clazz, Message message) {

0 commit comments

Comments
 (0)