Skip to content

Commit c8d3b1e

Browse files
committed
Allow omit a 'method' attribute on SqlProvider annotation
Fixes gh-1279
1 parent f738839 commit c8d3b1e

File tree

8 files changed

+334
-18
lines changed

8 files changed

+334
-18
lines changed

src/main/java/org/apache/ibatis/annotations/DeleteProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2016 the original author or authors.
2+
* Copyright 2009-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,5 +30,5 @@
3030
public @interface DeleteProvider {
3131
Class<?> type();
3232

33-
String method();
33+
String method() default "";
3434
}

src/main/java/org/apache/ibatis/annotations/InsertProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2016 the original author or authors.
2+
* Copyright 2009-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,5 +30,5 @@
3030
public @interface InsertProvider {
3131
Class<?> type();
3232

33-
String method();
33+
String method() default "";
3434
}

src/main/java/org/apache/ibatis/annotations/SelectProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2016 the original author or authors.
2+
* Copyright 2009-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,5 +30,5 @@
3030
public @interface SelectProvider {
3131
Class<?> type();
3232

33-
String method();
33+
String method() default "";
3434
}

src/main/java/org/apache/ibatis/annotations/UpdateProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2016 the original author or authors.
2+
* Copyright 2009-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,5 +30,5 @@
3030
public @interface UpdateProvider {
3131
Class<?> type();
3232

33-
String method();
33+
String method() default "";
3434
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* Copyright 2009-2019 the original author or authors.
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, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.apache.ibatis.builder.annotation;
18+
19+
import java.lang.reflect.Method;
20+
import java.util.Arrays;
21+
import java.util.Date;
22+
import java.util.List;
23+
import java.util.stream.Collectors;
24+
25+
import org.apache.ibatis.builder.BuilderException;
26+
27+
/**
28+
* The interface that resolve an SQL provider method via an SQL provider class.
29+
*
30+
* <p> This interface need to implements at an SQL provider class and
31+
* it need to define the default constructor for creating a new instance.
32+
*
33+
* @since 3.5.1
34+
* @author Kazuki Shimizu
35+
*/
36+
public interface ProviderMethodResolver {
37+
38+
/**
39+
* Resolve an SQL provider method.
40+
*
41+
* <p> The default implementation return a method that matches following conditions.
42+
* <ul>
43+
* <li>Method name matches with mapper method</li>
44+
* <li>Return type matches the {@link CharSequence}({@link String}, {@link StringBuilder}, etc...)</li>
45+
* </ul>
46+
* If matched method is zero or multiple, it throws a {@link BuilderException}.
47+
*
48+
* @param context a context for SQL provider
49+
* @return an SQL provider method
50+
* @throws BuilderException Throws when cannot resolve a target method
51+
*/
52+
default Method resolveMethod(ProviderContext context) {
53+
List<Method> targetMethods = Arrays.stream(getClass().getMethods())
54+
.filter(m -> m.getName().equals(context.getMapperMethod().getName()))
55+
.filter(m -> CharSequence.class.isAssignableFrom(m.getReturnType()))
56+
.collect(Collectors.toList());
57+
if (targetMethods.size() == 1) {
58+
return targetMethods.get(0);
59+
}
60+
if (targetMethods.isEmpty()) {
61+
throw new BuilderException("Cannot resolve the provide method because '"
62+
+ context.getMapperMethod().getName() + "' not found in SqlProvider '" + getClass().getName() + "'.");
63+
} else {
64+
throw new BuilderException("Cannot resolve the provide method because '"
65+
+ context.getMapperMethod().getName() + "' is found multiple in SqlProvider '" + getClass().getName() + "'.");
66+
}
67+
}
68+
69+
}

src/main/java/org/apache/ibatis/builder/annotation/ProviderSqlSource.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,21 @@ public ProviderSqlSource(Configuration configuration, Object provider, Class<?>
6262
this.providerType = (Class<?>) provider.getClass().getMethod("type").invoke(provider);
6363
providerMethodName = (String) provider.getClass().getMethod("method").invoke(provider);
6464

65-
for (Method m : this.providerType.getMethods()) {
66-
if (providerMethodName.equals(m.getName()) && CharSequence.class.isAssignableFrom(m.getReturnType())) {
67-
if (providerMethod != null) {
68-
throw new BuilderException("Error creating SqlSource for SqlProvider. Method '"
69-
+ providerMethodName + "' is found multiple in SqlProvider '" + this.providerType.getName()
70-
+ "'. Sql provider method can not overload.");
65+
if (providerMethodName.length() == 0 && ProviderMethodResolver.class.isAssignableFrom(this.providerType)) {
66+
this.providerMethod = ((ProviderMethodResolver) this.providerType.getDeclaredConstructor().newInstance())
67+
.resolveMethod(new ProviderContext(mapperType, mapperMethod));
68+
}
69+
if (this.providerMethod == null) {
70+
providerMethodName = providerMethodName.length() == 0 ? "provideSql" : providerMethodName;
71+
for (Method m : this.providerType.getMethods()) {
72+
if (providerMethodName.equals(m.getName()) && CharSequence.class.isAssignableFrom(m.getReturnType())) {
73+
if (this.providerMethod != null) {
74+
throw new BuilderException("Error creating SqlSource for SqlProvider. Method '"
75+
+ providerMethodName + "' is found multiple in SqlProvider '" + this.providerType.getName()
76+
+ "'. Sql provider method can not overload.");
77+
}
78+
this.providerMethod = m;
7179
}
72-
this.providerMethod = m;
73-
this.providerMethodArgumentNames = new ParamNameResolver(configuration, m).getNames();
74-
this.providerMethodParameterTypes = m.getParameterTypes();
7580
}
7681
}
7782
} catch (BuilderException e) {
@@ -83,6 +88,8 @@ public ProviderSqlSource(Configuration configuration, Object provider, Class<?>
8388
throw new BuilderException("Error creating SqlSource for SqlProvider. Method '"
8489
+ providerMethodName + "' not found in SqlProvider '" + this.providerType.getName() + "'.");
8590
}
91+
this.providerMethodArgumentNames = new ParamNameResolver(configuration, this.providerMethod).getNames();
92+
this.providerMethodParameterTypes = this.providerMethod.getParameterTypes();
8693
for (int i = 0; i < this.providerMethodParameterTypes.length; i++) {
8794
Class<?> parameterType = this.providerMethodParameterTypes[i];
8895
if (parameterType == ProviderContext.class) {

src/test/java/org/apache/ibatis/submitted/sqlprovider/CreateDB.sql

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--
2-
-- Copyright 2009-2017 the original author or authors.
2+
-- Copyright 2009-2019 the original author or authors.
33
--
44
-- Licensed under the Apache License, Version 2.0 (the "License");
55
-- you may not use this file except in compliance with the License.
@@ -15,15 +15,22 @@
1515
--
1616

1717
drop table users if exists;
18+
drop table memos if exists;
1819

1920
create table users (
2021
id int,
2122
name varchar(20),
2223
logical_delete boolean default false
2324
);
2425

26+
create table memos (
27+
id int,
28+
memo varchar(1024),
29+
);
30+
2531
insert into users (id, name) values(1, 'User1');
2632
insert into users (id, name) values(2, 'User2');
2733
insert into users (id, name) values(3, 'User3');
2834
insert into users (id, name, logical_delete) values(4, 'User4', true);
2935

36+
insert into memos (id, memo) values(1, 'memo1');

0 commit comments

Comments
 (0)