Skip to content

Commit cc9344b

Browse files
committed
Provider objects and test for multi-row inserts
1 parent 9e7a99b commit cc9344b

File tree

6 files changed

+142
-48
lines changed

6 files changed

+142
-48
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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.insert.render;
17+
18+
import java.util.ArrayList;
19+
import java.util.Collections;
20+
import java.util.List;
21+
import java.util.Objects;
22+
23+
public class DefaultMultiRowInsertStatementProvider<T> implements MultiRowInsertStatementProvider<T> {
24+
25+
private List<T> records;
26+
private String insertStatement;
27+
28+
private DefaultMultiRowInsertStatementProvider(Builder<T> builder) {
29+
insertStatement = Objects.requireNonNull(builder.insertStatement);
30+
records = Collections.unmodifiableList(builder.records);
31+
}
32+
33+
@Override
34+
public String getInsertStatement() {
35+
return insertStatement;
36+
}
37+
38+
@Override
39+
public List<T> getRecords() {
40+
return records;
41+
}
42+
43+
public static class Builder<T> {
44+
private List<T> records = new ArrayList<>();
45+
private String insertStatement;
46+
47+
public Builder<T> withRecords(List<T> records) {
48+
this.records.addAll(records);
49+
return this;
50+
}
51+
52+
public Builder<T> withInsertStatement(String insertStatement) {
53+
this.insertStatement = insertStatement;
54+
return this;
55+
}
56+
57+
public DefaultMultiRowInsertStatementProvider<T> build() {
58+
return new DefaultMultiRowInsertStatementProvider<>(this);
59+
}
60+
}
61+
}

src/main/java/org/mybatis/dynamic/sql/insert/render/MultiInsertStatementProvider.java

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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.insert.render;
17+
18+
import java.util.List;
19+
20+
public interface MultiRowInsertStatementProvider<T> {
21+
22+
String getInsertStatement();
23+
24+
List<T> getRecords();
25+
}

src/main/java/org/mybatis/dynamic/sql/util/SqlProviderAdapter.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2016-2017 the original author or authors.
2+
* Copyright 2016-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,10 +15,11 @@
1515
*/
1616
package org.mybatis.dynamic.sql.util;
1717

18+
import java.util.Map;
19+
1820
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
1921
import org.mybatis.dynamic.sql.insert.render.InsertSelectStatementProvider;
2022
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
21-
import org.mybatis.dynamic.sql.insert.render.MultiInsertStatementProvider;
2223
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
2324
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
2425

@@ -38,8 +39,8 @@ public String insert(InsertStatementProvider<?> insertStatement) {
3839
return insertStatement.getInsertStatement();
3940
}
4041

41-
public String multiInsert(MultiInsertStatementProvider insertStatement) {
42-
return insertStatement.getInsertStatement();
42+
public String multiInsert(Map<String, Object> parameter) {
43+
return (String) parameter.get("statement"); //$NON-NLS-1$
4344
}
4445

4546
public String insertSelect(InsertSelectStatementProvider insertStatement) {

src/test/java/examples/generated/always/mybatis/GeneratedAlwaysAnnotatedMapper.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2016-2017 the original author or authors.
2+
* Copyright 2016-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.
@@ -19,13 +19,14 @@
1919

2020
import org.apache.ibatis.annotations.InsertProvider;
2121
import org.apache.ibatis.annotations.Options;
22+
import org.apache.ibatis.annotations.Param;
2223
import org.apache.ibatis.annotations.Result;
2324
import org.apache.ibatis.annotations.ResultMap;
2425
import org.apache.ibatis.annotations.Results;
2526
import org.apache.ibatis.annotations.SelectProvider;
2627
import org.apache.ibatis.annotations.UpdateProvider;
2728
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
28-
import org.mybatis.dynamic.sql.insert.render.MultiInsertStatementProvider;
29+
import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
2930
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
3031
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
3132
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
@@ -50,10 +51,17 @@ public interface GeneratedAlwaysAnnotatedMapper {
5051
@Options(useGeneratedKeys=true, keyProperty="record.fullName")
5152
int insert(InsertStatementProvider<GeneratedAlwaysRecord> insertStatement);
5253

53-
@InsertProvider(type=SqlProviderAdapter.class, method="multiInsert")
54-
@Options(useGeneratedKeys=true, keyProperty="fullName")
55-
int multiInsert(MultiInsertStatementProvider multiInsert);
56-
5754
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
5855
int update(UpdateStatementProvider updateStatement);
56+
57+
@InsertProvider(type=SqlProviderAdapter.class, method="multiInsert")
58+
@Options(useGeneratedKeys=true, keyProperty="records.fullName")
59+
int multiInsert(@Param("statement") String statement, @Param("records") List<GeneratedAlwaysRecord> records);
60+
61+
// TODO - this is kludgy. Currently MyBatis does not support nested lists in parameter objects,
62+
// so we need to do this silliness and decompose the multi insert into its component parts
63+
// for the actual MyBatis call
64+
default int multiInsert(MultiRowInsertStatementProvider<GeneratedAlwaysRecord> multiInsert) {
65+
return multiInsert(multiInsert.getInsertStatement(), multiInsert.getRecords());
66+
}
5967
}

src/test/java/examples/generated/always/mybatis/GeneratedAlwaysAnnotatedMapperTest.java

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2016-2018 the original author or authors.
2+
* Copyright 2016-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.
@@ -51,7 +51,8 @@
5151
import org.junit.jupiter.api.BeforeEach;
5252
import org.junit.jupiter.api.Test;
5353
import org.mybatis.dynamic.sql.insert.render.BatchInsert;
54-
import org.mybatis.dynamic.sql.insert.render.MultiInsertStatementProvider;
54+
import org.mybatis.dynamic.sql.insert.render.DefaultMultiRowInsertStatementProvider;
55+
import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
5556
import org.mybatis.dynamic.sql.render.RenderingStrategy;
5657
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
5758
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
@@ -193,6 +194,31 @@ public void testBatchInsertWithArray() {
193194
}
194195
}
195196

197+
@Test
198+
public void testMultiInsertWithRawMyBatisAnnotations() {
199+
try (SqlSession session = sqlSessionFactory.openSession()) {
200+
GeneratedAlwaysAnnotatedMapper mapper = session.getMapper(GeneratedAlwaysAnnotatedMapper.class);
201+
List<GeneratedAlwaysRecord> records = getTestRecords();
202+
203+
String statement = "insert into GeneratedAlways (id, first_name, last_name)" +
204+
" values" +
205+
" (#{records[0].id,jdbcType=INTEGER}, #{records[0].firstName,jdbcType=VARCHAR}, #{records[0].lastName,jdbcType=VARCHAR})," +
206+
" (#{records[1].id,jdbcType=INTEGER}, #{records[1].firstName,jdbcType=VARCHAR}, #{records[1].lastName,jdbcType=VARCHAR})," +
207+
" (#{records[2].id,jdbcType=INTEGER}, #{records[2].firstName,jdbcType=VARCHAR}, #{records[2].lastName,jdbcType=VARCHAR})," +
208+
" (#{records[3].id,jdbcType=INTEGER}, #{records[3].firstName,jdbcType=VARCHAR}, #{records[3].lastName,jdbcType=VARCHAR})";
209+
210+
int rows = mapper.multiInsert(statement, records);
211+
212+
assertAll(
213+
() -> assertThat(rows).isEqualTo(4),
214+
() -> assertThat(records.get(0).getFullName()).isEqualTo("George Jetson"),
215+
() -> assertThat(records.get(1).getFullName()).isEqualTo("Jane Jetson"),
216+
() -> assertThat(records.get(2).getFullName()).isEqualTo("Judy Jetson"),
217+
() -> assertThat(records.get(3).getFullName()).isEqualTo("Elroy Jetson")
218+
);
219+
}
220+
}
221+
196222
@Test
197223
public void testMultiInsertWithList() {
198224
try (SqlSession session = sqlSessionFactory.openSession()) {
@@ -207,18 +233,18 @@ public void testMultiInsertWithList() {
207233
// .build()
208234
// .render(RenderingStrategy.MYBATIS3);
209235

210-
MultiInsertStatementProvider insertStatement = new MultiInsertStatementProvider();
211-
212236
String statement = "insert into GeneratedAlways (id, first_name, last_name)" +
213-
" values (#{list[0].id,jdbcType=INTEGER}, #{list[0].firstName,jdbcType=VARCHAR}, #{list[0].lastName,jdbcType=VARCHAR})," +
214-
" (#{list[1].id,jdbcType=INTEGER}, #{list[1].firstName,jdbcType=VARCHAR}, #{list[1].lastName,jdbcType=VARCHAR})," +
215-
" (#{list[2].id,jdbcType=INTEGER}, #{list[2].firstName,jdbcType=VARCHAR}, #{list[2].lastName,jdbcType=VARCHAR})," +
216-
" (#{list[3].id,jdbcType=INTEGER}, #{list[3].firstName,jdbcType=VARCHAR}, #{list[3].lastName,jdbcType=VARCHAR})";
237+
" values" +
238+
" (#{records[0].id,jdbcType=INTEGER}, #{records[0].firstName,jdbcType=VARCHAR}, #{records[0].lastName,jdbcType=VARCHAR})," +
239+
" (#{records[1].id,jdbcType=INTEGER}, #{records[1].firstName,jdbcType=VARCHAR}, #{records[1].lastName,jdbcType=VARCHAR})," +
240+
" (#{records[2].id,jdbcType=INTEGER}, #{records[2].firstName,jdbcType=VARCHAR}, #{records[2].lastName,jdbcType=VARCHAR})," +
241+
" (#{records[3].id,jdbcType=INTEGER}, #{records[3].firstName,jdbcType=VARCHAR}, #{records[3].lastName,jdbcType=VARCHAR})";
217242

218-
insertStatement.setInsertStatement(statement);
219-
insertStatement.setList(records);
243+
MultiRowInsertStatementProvider<GeneratedAlwaysRecord> insertStatement = new DefaultMultiRowInsertStatementProvider.Builder<GeneratedAlwaysRecord>()
244+
.withInsertStatement(statement)
245+
.withRecords(records)
246+
.build();
220247

221-
// must use a Map...MyBatis is broken for using real objects
222248
mapper.multiInsert(insertStatement);
223249

224250
assertAll(

0 commit comments

Comments
 (0)