View Javadoc
1   /*
2    *    Copyright 2016-2025 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    *       https://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 examples.simple;
17  
18  import static examples.simple.CompoundKeyDynamicSqlSupport.compoundKey;
19  import static examples.simple.CompoundKeyDynamicSqlSupport.id1;
20  import static examples.simple.CompoundKeyDynamicSqlSupport.id2;
21  import static org.assertj.core.api.Assertions.assertThat;
22  import static org.mybatis.dynamic.sql.SqlBuilder.insert;
23  import static org.mybatis.dynamic.sql.SqlBuilder.insertBatch;
24  import static org.mybatis.dynamic.sql.SqlBuilder.insertMultiple;
25  import static org.mybatis.dynamic.sql.SqlBuilder.select;
26  
27  import java.io.InputStream;
28  import java.io.InputStreamReader;
29  import java.sql.Connection;
30  import java.sql.DriverManager;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.function.Function;
34  import java.util.stream.IntStream;
35  
36  import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
37  import org.apache.ibatis.executor.BatchResult;
38  import org.apache.ibatis.jdbc.ScriptRunner;
39  import org.apache.ibatis.mapping.Environment;
40  import org.apache.ibatis.session.Configuration;
41  import org.apache.ibatis.session.ExecutorType;
42  import org.apache.ibatis.session.SqlSession;
43  import org.apache.ibatis.session.SqlSessionFactory;
44  import org.apache.ibatis.session.SqlSessionFactoryBuilder;
45  import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
46  import org.junit.jupiter.api.BeforeEach;
47  import org.junit.jupiter.api.Test;
48  import org.mybatis.dynamic.sql.insert.render.BatchInsert;
49  import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
50  import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
51  import org.mybatis.dynamic.sql.render.RenderingStrategies;
52  import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
53  
54  class MyBatisMapToRowTest {
55      private static final String JDBC_URL = "jdbc:hsqldb:mem:aname";
56      private static final String JDBC_DRIVER = "org.hsqldb.jdbcDriver";
57      private SqlSessionFactory sqlSessionFactory;
58  
59      @BeforeEach
60      void setup() throws Exception {
61          Class.forName(JDBC_DRIVER);
62          InputStream is = getClass().getResourceAsStream("/examples/simple/CreateSimpleDB.sql");
63          assert is != null;
64          try (Connection connection = DriverManager.getConnection(JDBC_URL, "sa", "")) {
65              ScriptRunner sr = new ScriptRunner(connection);
66              sr.setLogWriter(null);
67              sr.runScript(new InputStreamReader(is));
68          }
69  
70          UnpooledDataSource ds = new UnpooledDataSource(JDBC_DRIVER, JDBC_URL, "sa", "");
71          Environment environment = new Environment("test", new JdbcTransactionFactory(), ds);
72          Configuration config = new Configuration(environment);
73          config.addMapper(CompoundKeyMapper.class);
74          sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
75      }
76  
77      @Test
78      void testInsertOne() {
79          try (SqlSession session = sqlSessionFactory.openSession()) {
80              CompoundKeyMapper mapper = session.getMapper(CompoundKeyMapper.class);
81  
82              Integer i = 1;
83  
84              InsertStatementProvider<Integer> insertStatement = insert(i)
85                      .into(compoundKey)
86                      .map(id1).toConstant("22")
87                      .map(id2).toRow()
88                      .build()
89                      .render(RenderingStrategies.MYBATIS3);
90  
91              String expected = "insert into CompoundKey (id1, id2) values (22, #{row,jdbcType=INTEGER})";
92              assertThat(insertStatement.getInsertStatement()).isEqualTo(expected);
93  
94              int rows = mapper.insert(insertStatement);
95              assertThat(rows).isEqualTo(1);
96  
97              SelectStatementProvider selectStatement = select(id1, id2)
98                      .from(compoundKey)
99                      .orderBy(id1, id2)
100                     .build().render(RenderingStrategies.MYBATIS3);
101 
102             List<CompoundKeyRow> records = mapper.selectMany(selectStatement, rowMapper);
103             assertThat(records).hasSize(1);
104         }
105     }
106 
107     @Test
108     void testInsertMultiple() {
109         try (SqlSession session = sqlSessionFactory.openSession()) {
110             CompoundKeyMapper mapper = session.getMapper(CompoundKeyMapper.class);
111 
112             List<Integer> integers = List.of(1, 2, 3);
113 
114             MultiRowInsertStatementProvider<Integer> insertStatement = insertMultiple(integers)
115                     .into(compoundKey)
116                     .map(id1).toConstant("22")
117                     .map(id2).toRow()
118                     .build()
119                     .render(RenderingStrategies.MYBATIS3);
120 
121             String expected = "insert into CompoundKey (id1, id2) values (22, #{records[0],jdbcType=INTEGER}), (22, #{records[1],jdbcType=INTEGER}), (22, #{records[2],jdbcType=INTEGER})";
122             assertThat(insertStatement.getInsertStatement()).isEqualTo(expected);
123 
124             int rows = mapper.insertMultiple(insertStatement);
125             assertThat(rows).isEqualTo(3);
126 
127             SelectStatementProvider selectStatement = select(id1, id2)
128                     .from(compoundKey)
129                     .orderBy(id1, id2)
130                     .build().render(RenderingStrategies.MYBATIS3);
131 
132             List<CompoundKeyRow> records = mapper.selectMany(selectStatement, rowMapper);
133             assertThat(records).hasSize(3);
134         }
135     }
136 
137     @Test
138     void testInsertBatch() {
139         try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
140             CompoundKeyMapper mapper = session.getMapper(CompoundKeyMapper.class);
141 
142             List<Integer> integers = List.of(1, 2, 3);
143 
144             BatchInsert<Integer> insertStatement = insertBatch(integers)
145                     .into(compoundKey)
146                     .map(id1).toConstant("22")
147                     .map(id2).toRow()
148                     .build()
149                     .render(RenderingStrategies.MYBATIS3);
150 
151             String expected = "insert into CompoundKey (id1, id2) values (22, #{row,jdbcType=INTEGER})";
152             assertThat(insertStatement.getInsertStatementSQL()).isEqualTo(expected);
153 
154             insertStatement.insertStatements().forEach(mapper::insert);
155 
156             List<BatchResult> batchResults = mapper.flush();
157 
158             int rows = batchResults.stream()
159                     .map(BatchResult::getUpdateCounts)
160                     .flatMapToInt(IntStream::of)
161                     .sum();
162             assertThat(rows).isEqualTo(3);
163 
164             SelectStatementProvider selectStatement = select(id1, id2)
165                     .from(compoundKey)
166                     .orderBy(id1, id2)
167                     .build().render(RenderingStrategies.MYBATIS3);
168 
169             List<CompoundKeyRow> records = mapper.selectMany(selectStatement, rowMapper);
170             assertThat(records).hasSize(3);
171         }
172     }
173 
174     private final Function<Map<String, Object>, CompoundKeyRow> rowMapper =
175             m -> new CompoundKeyRow((Integer) m.get("ID1"), (Integer) m.get("ID2"));
176 }