Skip to content

Commit d17e8c3

Browse files
authored
Merge pull request #125 from jeffgbutler/better-update-by-example
Add Utility Classes and Pattern for Improved General Mappers
2 parents abf407e + c5b5e16 commit d17e8c3

17 files changed

+768
-430
lines changed

README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ One capability is that very expressive dynamic queries can be generated. Here's
5656
```java
5757
@Test
5858
public void testComplexCondition() {
59-
SqlSession sqlSession = sqlSessionFactory.openSession();
60-
try {
59+
try(SqlSession sqlSession = sqlSessionFactory.openSession()) {
6160
AnimalDataMapper mapper = sqlSession.getMapper(AnimalDataMapper.class);
6261

6362
SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight)
@@ -72,8 +71,6 @@ One capability is that very expressive dynamic queries can be generated. Here's
7271

7372
List<AnimalData> animals = mapper.selectMany(selectStatement);
7473
assertThat(animals.size()).isEqualTo(4);
75-
} finally {
76-
sqlSession.close();
7774
}
7875
}
7976
```

src/main/java/org/mybatis/dynamic/sql/util/mybatis3/MyBatis3CountByExampleHelper.java renamed to src/main/java/org/mybatis/dynamic/sql/util/mybatis3/MyBatis3CountHelper.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import org.mybatis.dynamic.sql.util.Buildable;
2323

2424
/**
25-
* Represents a function that can be used to create a "CountByExample" method in the style
25+
* Represents a function that can be used to create a general count method in the style
2626
* of MyBatis Generator. When using this function, you can create a method that does not require a user to
2727
* call the build().execute() methods - making client code look a bit cleaner.
2828
*
@@ -32,7 +32,7 @@
3232
* &#64;SelectProvider(type=SqlProviderAdapter.class, method="select")
3333
* long count(SelectStatementProvider selectStatement);
3434
*
35-
* default long countByExample(MyBatis3CountByExampleHelper helper) {
35+
* default long count(MyBatis3CountHelper helper) {
3636
* return helper.apply(SelectDSL.selectWithMapper(this::count, SqlBuilder.count())
3737
* .from(simpleTable))
3838
* .build()
@@ -43,34 +43,34 @@
4343
* <p>And then call the simplified default method like this:
4444
*
4545
* <pre>
46-
* long rows = mapper.countByExample(q -&gt;
46+
* long rows = mapper.count(q -&gt;
4747
* q.where(occupation, isNull()));
4848
* </pre>
4949
*
5050
* <p>You can implement a "count all" with the following code:
5151
*
5252
* <pre>
53-
* long rows = mapper.countByExample(q -&gt; q);
53+
* long rows = mapper.count(q -&gt; q);
5454
* </pre>
5555
*
5656
* <p>Or
5757
*
5858
* <pre>
59-
* long rows = mapper.countByExample(MyBatis3CountByExampleHelper.allRows());
59+
* long rows = mapper.count(MyBatis3CountHelper.allRows());
6060
* </pre>
6161
*
6262
* @author Jeff Butler
6363
*/
6464
@FunctionalInterface
65-
public interface MyBatis3CountByExampleHelper extends
65+
public interface MyBatis3CountHelper extends
6666
Function<QueryExpressionDSL<MyBatis3SelectModelAdapter<Long>>, Buildable<MyBatis3SelectModelAdapter<Long>>> {
6767

6868
/**
6969
* Returns a helper that can be used to count every row in a table.
7070
*
7171
* @return the helper that will count every row in a table
7272
*/
73-
static MyBatis3CountByExampleHelper allRows() {
73+
static MyBatis3CountHelper allRows() {
7474
return h -> h;
7575
}
7676
}

src/main/java/org/mybatis/dynamic/sql/util/mybatis3/MyBatis3DeleteByExampleHelper.java renamed to src/main/java/org/mybatis/dynamic/sql/util/mybatis3/MyBatis3DeleteHelper.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@
1818
import java.util.function.Function;
1919

2020
import org.mybatis.dynamic.sql.delete.DeleteDSL;
21-
import org.mybatis.dynamic.sql.delete.MyBatis3DeleteModelAdapter;
2221
import org.mybatis.dynamic.sql.util.Buildable;
2322

2423
/**
25-
* Represents a function that can be used to create a "DeleteByExample" method in the style
24+
* Represents a function that can be used to create a general delete method in the style
2625
* of MyBatis Generator. When using this function, you can create a method that does not require a user to
2726
* call the build().execute() methods - making client code look a bit cleaner.
2827
*
@@ -32,7 +31,7 @@
3231
* &#64;DeleteProvider(type=SqlProviderAdapter.class, method="delete")
3332
* int delete(DeleteStatementProvider deleteStatement);
3433
*
35-
* default int deleteByExample(MyBatis3DeleteByExampleHelper helper) {
34+
* default int delete(MyBatis3DeleteHelper helper) {
3635
* return helper.apply(DeleteDSL.deleteFromWithMapper(this::delete, simpleTable))
3736
* .build()
3837
* .execute();
@@ -42,34 +41,34 @@
4241
* <p>And then call the simplified default method like this:
4342
*
4443
* <pre>
45-
* int rows = mapper.deleteByExample(q -&gt;
44+
* int rows = mapper.delete(q -&gt;
4645
* q.where(occupation, isNull()));
4746
* </pre>
4847
*
4948
* <p>You can implement a "delete all" with the following code:
5049
*
5150
* <pre>
52-
* int rows = mapper.deleteByExample(q -&gt; q);
51+
* int rows = mapper.delete(q -&gt; q);
5352
* </pre>
5453
*
5554
* <p>Or
5655
*
5756
* <pre>
58-
* long rows = mapper.deleteByExample(MyBatis3DeleteByExampleHelper.allRows());
57+
* long rows = mapper.delete(MyBatis3DeleteHelper.allRows());
5958
* </pre>
6059
6160
* @author Jeff Butler
6261
*/
6362
@FunctionalInterface
64-
public interface MyBatis3DeleteByExampleHelper extends
65-
Function<DeleteDSL<MyBatis3DeleteModelAdapter<Integer>>, Buildable<MyBatis3DeleteModelAdapter<Integer>>> {
63+
public interface MyBatis3DeleteHelper extends
64+
Function<DeleteDSL<MyBatis3DeleteModelToIntAdapter>, Buildable<MyBatis3DeleteModelToIntAdapter>> {
6665

6766
/**
6867
* Returns a helper that can be used to delete every row in a table.
6968
*
7069
* @return the helper that will delete every row in a table
7170
*/
72-
static MyBatis3DeleteByExampleHelper allRows() {
71+
static MyBatis3DeleteHelper allRows() {
7372
return h -> h;
7473
}
7574
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* Copyright 2016-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+
package org.mybatis.dynamic.sql.util.mybatis3;
17+
18+
import java.util.Objects;
19+
import java.util.function.ToIntFunction;
20+
21+
import org.mybatis.dynamic.sql.delete.DeleteModel;
22+
import org.mybatis.dynamic.sql.delete.MyBatis3DeleteModelAdapter;
23+
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
24+
import org.mybatis.dynamic.sql.render.RenderingStrategy;
25+
26+
/**
27+
* This adapter will render the underlying delete model for MyBatis3, and then call a MyBatis mapper method.
28+
* This version of the adapter is preferred over {@link MyBatis3DeleteModelAdapter} because it is not generic
29+
* and does not force a box/unbox for mappers that always return a primitive int.
30+
*
31+
* @see MyBatis3Utils
32+
*
33+
* @author Jeff Butler
34+
*
35+
*/
36+
public class MyBatis3DeleteModelToIntAdapter {
37+
38+
private DeleteModel deleteModel;
39+
private ToIntFunction<DeleteStatementProvider> mapperMethod;
40+
41+
private MyBatis3DeleteModelToIntAdapter(DeleteModel deleteModel,
42+
ToIntFunction<DeleteStatementProvider> mapperMethod) {
43+
this.deleteModel = Objects.requireNonNull(deleteModel);
44+
this.mapperMethod = Objects.requireNonNull(mapperMethod);
45+
}
46+
47+
public int execute() {
48+
return mapperMethod.applyAsInt(deleteStatement());
49+
}
50+
51+
private DeleteStatementProvider deleteStatement() {
52+
return deleteModel.render(RenderingStrategy.MYBATIS3);
53+
}
54+
55+
public static MyBatis3DeleteModelToIntAdapter of(DeleteModel deleteModel,
56+
ToIntFunction<DeleteStatementProvider> mapperMethod) {
57+
return new MyBatis3DeleteModelToIntAdapter(deleteModel, mapperMethod);
58+
}
59+
}

src/main/java/org/mybatis/dynamic/sql/util/mybatis3/MyBatis3SelectByExampleHelper.java renamed to src/main/java/org/mybatis/dynamic/sql/util/mybatis3/MyBatis3SelectListHelper.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import org.mybatis.dynamic.sql.util.Buildable;
2525

2626
/**
27-
* Represents a function that can be used to create a "SelectByExample" method in the style
27+
* Represents a function that can be used to create a general select method in the style
2828
* of MyBatis Generator. When using this function, you can create a method that does not require a user to
2929
* call the build().execute() methods - making client code look a bit cleaner.
3030
*
@@ -42,7 +42,7 @@
4242
* })
4343
* List&lt;SimpleRecord&gt; selectMany(SelectStatementProvider selectStatement);
4444
*
45-
* default List&lt;SimpleRecord&gt; selectByExample(MyBatis3SelectByExampleHelper&lt;SimpleRecord&gt; helper) {
45+
* default List&lt;SimpleRecord&gt; select(MyBatis3SelectHelper&lt;SimpleRecord&gt; helper) {
4646
* return helper.apply(SelectDSL.selectWithMapper(this::selectMany, simpleTable.allColumns())
4747
* .from(simpleTable))
4848
* .build()
@@ -53,27 +53,27 @@
5353
* <p>And then call the simplified default method like this:
5454
*
5555
* <pre>
56-
* List&lt;SimpleRecord&gt; rows = mapper.selectByExample(q -&gt;
56+
* List&lt;SimpleRecord&gt; rows = mapper.select(q -&gt;
5757
* q.where(id, isEqualTo(1))
5858
* .or(occupation, isNull()));
5959
* </pre>
6060
*
6161
* <p>You can implement a "select all" with the following code:
6262
*
6363
* <pre>
64-
* List&lt;SimpleRecord&gt; rows = mapper.selectByExample(q -&gt; q);
64+
* List&lt;SimpleRecord&gt; rows = mapper.select(q -&gt; q);
6565
* </pre>
6666
*
6767
* <p>Or
6868
*
6969
* <pre>
70-
* List&lt;SimpleRecord&gt; rows = mapper.selectByExample(MyBatis3SelectByExampleHelper.allRows());
70+
* List&lt;SimpleRecord&gt; rows = mapper.select(MyBatis3SelectHelper.allRows());
7171
* </pre>
7272
*
7373
* @author Jeff Butler
7474
*/
7575
@FunctionalInterface
76-
public interface MyBatis3SelectByExampleHelper<T> extends
76+
public interface MyBatis3SelectListHelper<T> extends
7777
Function<QueryExpressionDSL<MyBatis3SelectModelAdapter<List<T>>>,
7878
Buildable<MyBatis3SelectModelAdapter<List<T>>>> {
7979

@@ -84,7 +84,7 @@ public interface MyBatis3SelectByExampleHelper<T> extends
8484
*
8585
* @return the helper that will select every row in a table
8686
*/
87-
static <T> MyBatis3SelectByExampleHelper<T> allRows() {
87+
static <T> MyBatis3SelectListHelper<T> allRows() {
8888
return h -> h;
8989
}
9090

@@ -96,7 +96,7 @@ static <T> MyBatis3SelectByExampleHelper<T> allRows() {
9696
*
9797
* @return the helper that will select every row in a table in the specified order
9898
*/
99-
static <T> MyBatis3SelectByExampleHelper<T> allRowsOrderdBy(SortSpecification...columns) {
99+
static <T> MyBatis3SelectListHelper<T> allRowsOrderdBy(SortSpecification...columns) {
100100
return h -> h.orderBy(columns);
101101
}
102102
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Copyright 2016-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+
package org.mybatis.dynamic.sql.util.mybatis3;
17+
18+
import java.util.Optional;
19+
import java.util.function.Function;
20+
21+
import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter;
22+
import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
23+
import org.mybatis.dynamic.sql.util.Buildable;
24+
25+
/**
26+
* Represents a function that can be used to create a general select one method in the style
27+
* of MyBatis Generator. When using this function, you can create a method that does not require a user to
28+
* call the build().execute() methods - making client code look a bit cleaner.
29+
*
30+
* <p>For example, you can create mapper interface methods like this:
31+
*
32+
* <pre>
33+
* &#64;SelectProvider(type=SqlProviderAdapter.class, method="select")
34+
* &#64;ResultMap("SimpleTableResult")
35+
* Optional&lt;SimpleTableRecord&gt; selectOne(SelectStatementProvider selectStatement);
36+
*
37+
* default Optional&lt;SimpleTableRecord&gt; selectOne(MyBatis3SelectOneHelper&lt;SimpleTableRecord&gt; helper) {
38+
* return helper.apply(SelectDSL.selectWithMapper(this::selectOne, simpleTable.allColumns())
39+
* .from(simpleTable))
40+
* .build()
41+
* .execute();
42+
* }
43+
* </pre>
44+
*
45+
* <p>And then call the simplified default method like this:
46+
*
47+
* <pre>
48+
* Optional&lt;SimpleRecord&gt; record = mapper.selectOne(q -&gt;
49+
* q.where(id, isEqualTo(1)));
50+
* </pre>
51+
*
52+
* @author Jeff Butler
53+
*/
54+
@FunctionalInterface
55+
public interface MyBatis3SelectOneHelper<T> extends
56+
Function<QueryExpressionDSL<MyBatis3SelectModelAdapter<Optional<T>>>,
57+
Buildable<MyBatis3SelectModelAdapter<Optional<T>>>> {
58+
}

0 commit comments

Comments
 (0)