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.mariadb;
17  
18  import static org.assertj.core.api.Assertions.assertThat;
19  
20  import static examples.mariadb.ItemsDynamicSQLSupport.amount;
21  import static examples.mariadb.ItemsDynamicSQLSupport.id;
22  import static examples.mariadb.ItemsDynamicSQLSupport.items;
23  import static examples.mariadb.ItemsDynamicSQLSupport.description;
24  import static org.assertj.core.api.Assertions.entry;
25  import static org.mybatis.dynamic.sql.SqlBuilder.add;
26  import static org.mybatis.dynamic.sql.SqlBuilder.constant;
27  import static org.mybatis.dynamic.sql.SqlBuilder.deleteFrom;
28  import static org.mybatis.dynamic.sql.SqlBuilder.isLessThan;
29  import static org.mybatis.dynamic.sql.SqlBuilder.select;
30  import static org.mybatis.dynamic.sql.SqlBuilder.update;
31  
32  import config.TestContainersConfiguration;
33  import java.util.List;
34  import java.util.Map;
35  
36  import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
37  import org.apache.ibatis.mapping.Environment;
38  import org.apache.ibatis.session.Configuration;
39  import org.apache.ibatis.session.SqlSession;
40  import org.apache.ibatis.session.SqlSessionFactory;
41  import org.apache.ibatis.session.SqlSessionFactoryBuilder;
42  import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
43  import org.junit.jupiter.api.BeforeAll;
44  import org.junit.jupiter.api.Test;
45  import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
46  import org.mybatis.dynamic.sql.render.RenderingStrategies;
47  import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
48  import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
49  import org.mybatis.dynamic.sql.util.mybatis3.CommonDeleteMapper;
50  import org.mybatis.dynamic.sql.util.mybatis3.CommonSelectMapper;
51  import org.mybatis.dynamic.sql.util.mybatis3.CommonUpdateMapper;
52  import org.testcontainers.containers.MariaDBContainer;
53  import org.testcontainers.junit.jupiter.Container;
54  import org.testcontainers.junit.jupiter.Testcontainers;
55  
56  
57  @Testcontainers
58  class MariaDBTest {
59  
60      @SuppressWarnings("resource")
61      @Container
62      private static final MariaDBContainer<?> mariadb =
63              new MariaDBContainer<>(TestContainersConfiguration.MARIADB_LATEST)
64                      .withInitScript("examples/mariadb/CreateDB.sql");
65  
66      private static SqlSessionFactory sqlSessionFactory;
67  
68      @BeforeAll
69      static void setup() {
70          UnpooledDataSource ds = new UnpooledDataSource(mariadb.getDriverClassName(), mariadb.getJdbcUrl(),
71                  mariadb.getUsername(), mariadb.getPassword());
72          Environment environment = new Environment("test", new JdbcTransactionFactory(), ds);
73          Configuration config = new Configuration(environment);
74          config.addMapper(CommonDeleteMapper.class);
75          config.addMapper(CommonSelectMapper.class);
76          config.addMapper(CommonUpdateMapper.class);
77          sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
78      }
79  
80      @Test
81      void smokeTest() {
82          try (SqlSession session = sqlSessionFactory.openSession()) {
83              CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class);
84  
85              SelectStatementProvider selectStatement = select(id, description)
86                      .from(items)
87                      .orderBy(id)
88                      .build()
89                      .render(RenderingStrategies.MYBATIS3);
90               List<Map<String, Object>> rows = mapper.selectManyMappedRows(selectStatement);
91               assertThat(rows).hasSize(20);
92          }
93      }
94  
95      @Test
96      void testDeleteWithLimit() {
97          try (SqlSession session = sqlSessionFactory.openSession()) {
98              CommonDeleteMapper mapper = session.getMapper(CommonDeleteMapper.class);
99  
100             DeleteStatementProvider deleteStatement = deleteFrom(items)
101                     .limit(5)
102                     .build()
103                     .render(RenderingStrategies.MYBATIS3);
104 
105             assertThat(deleteStatement.getDeleteStatement())
106                     .isEqualTo("delete from items limit #{parameters.p1}");
107             assertThat(deleteStatement.getParameters()).containsOnly(entry("p1", 5L));
108 
109             int rows = mapper.delete(deleteStatement);
110             assertThat(rows).isEqualTo(5);
111         }
112     }
113 
114     @Test
115     void testDeleteWithOrderBy() {
116         try (SqlSession session = sqlSessionFactory.openSession()) {
117             CommonDeleteMapper mapper = session.getMapper(CommonDeleteMapper.class);
118 
119             DeleteStatementProvider deleteStatement = deleteFrom(items)
120                     .orderBy(amount.descending())
121                     .build()
122                     .render(RenderingStrategies.MYBATIS3);
123 
124             assertThat(deleteStatement.getDeleteStatement())
125                     .isEqualTo("delete from items order by amount DESC");
126             assertThat(deleteStatement.getParameters()).isEmpty();
127 
128             int rows = mapper.delete(deleteStatement);
129             assertThat(rows).isEqualTo(20);
130         }
131     }
132 
133     @Test
134     void testDeleteWithOrderByAndLimit() {
135         try (SqlSession session = sqlSessionFactory.openSession()) {
136             CommonDeleteMapper mapper = session.getMapper(CommonDeleteMapper.class);
137 
138             DeleteStatementProvider deleteStatement = deleteFrom(items)
139                     .orderBy(amount.descending())
140                     .limit(5)
141                     .build()
142                     .render(RenderingStrategies.MYBATIS3);
143 
144             assertThat(deleteStatement.getDeleteStatement())
145                     .isEqualTo("delete from items order by amount DESC limit #{parameters.p1}");
146             assertThat(deleteStatement.getParameters()).containsOnly(entry("p1", 5L));
147 
148             int rows = mapper.delete(deleteStatement);
149             assertThat(rows).isEqualTo(5);
150         }
151     }
152 
153     @Test
154     void testDeleteWithWhereAndLimit() {
155         try (SqlSession session = sqlSessionFactory.openSession()) {
156             CommonDeleteMapper mapper = session.getMapper(CommonDeleteMapper.class);
157 
158             DeleteStatementProvider deleteStatement = deleteFrom(items)
159                     .where(id, isLessThan(10))
160                     .limit(5)
161                     .build()
162                     .render(RenderingStrategies.MYBATIS3);
163 
164             String expected = "delete from items where id < #{parameters.p1,jdbcType=INTEGER} limit #{parameters.p2}";
165             assertThat(deleteStatement.getDeleteStatement()).isEqualTo(expected);
166             assertThat(deleteStatement.getParameters()).containsOnly(entry("p1", 10), entry("p2", 5L));
167 
168             int rows = mapper.delete(deleteStatement);
169             assertThat(rows).isEqualTo(5);
170         }
171     }
172 
173     @Test
174     void testDeleteWithWhereAndOrderBy() {
175         try (SqlSession session = sqlSessionFactory.openSession()) {
176             CommonDeleteMapper mapper = session.getMapper(CommonDeleteMapper.class);
177 
178             DeleteStatementProvider deleteStatement = deleteFrom(items)
179                     .where(id, isLessThan(10))
180                     .orderBy(amount.descending())
181                     .build()
182                     .render(RenderingStrategies.MYBATIS3);
183 
184             String expected = "delete from items where id < #{parameters.p1,jdbcType=INTEGER} order by amount DESC";
185             assertThat(deleteStatement.getDeleteStatement()).isEqualTo(expected);
186             assertThat(deleteStatement.getParameters()).containsOnly(entry("p1", 10));
187 
188             int rows = mapper.delete(deleteStatement);
189             assertThat(rows).isEqualTo(9);
190         }
191     }
192 
193     @Test
194     void testDeleteWithWhereAndOrderByAndLimit() {
195         try (SqlSession session = sqlSessionFactory.openSession()) {
196             CommonDeleteMapper mapper = session.getMapper(CommonDeleteMapper.class);
197 
198             DeleteStatementProvider deleteStatement = deleteFrom(items)
199                     .where(id, isLessThan(10))
200                     .orderBy(amount)
201                     .limit(5)
202                     .build()
203                     .render(RenderingStrategies.MYBATIS3);
204 
205             String expected = "delete from items where id < #{parameters.p1,jdbcType=INTEGER} order by amount "
206                     + "limit #{parameters.p2}";
207             assertThat(deleteStatement.getDeleteStatement()).isEqualTo(expected);
208             assertThat(deleteStatement.getParameters()).containsOnly(entry("p1", 10), entry("p2", 5L));
209 
210             int rows = mapper.delete(deleteStatement);
211             assertThat(rows).isEqualTo(5);
212         }
213     }
214 
215     @Test
216     void testUpdateWithLimit() {
217         try (SqlSession session = sqlSessionFactory.openSession()) {
218             CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
219 
220             UpdateStatementProvider updateStatement = update(items)
221                     .set(amount).equalTo(add(amount, constant("100")))
222                     .limit(5)
223                     .build()
224                     .render(RenderingStrategies.MYBATIS3);
225 
226             String expected = "update items set amount = (amount + 100) limit #{parameters.p1}";
227             assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected);
228             assertThat(updateStatement.getParameters()).containsOnly(entry("p1", 5L));
229 
230             int rows = mapper.update(updateStatement);
231             assertThat(rows).isEqualTo(5);
232         }
233     }
234 
235     @Test
236     void testUpdateWithOrderBy() {
237         try (SqlSession session = sqlSessionFactory.openSession()) {
238             CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
239 
240             UpdateStatementProvider updateStatement = update(items)
241                     .set(amount).equalTo(add(amount, constant("100")))
242                     .orderBy(amount.descending())
243                     .build()
244                     .render(RenderingStrategies.MYBATIS3);
245 
246             assertThat(updateStatement.getUpdateStatement())
247                     .isEqualTo("update items set amount = (amount + 100) order by amount DESC");
248             assertThat(updateStatement.getParameters()).isEmpty();
249 
250             int rows = mapper.update(updateStatement);
251             assertThat(rows).isEqualTo(20);
252         }
253     }
254 
255     @Test
256     void testUpdateWithOrderByAndLimit() {
257         try (SqlSession session = sqlSessionFactory.openSession()) {
258             CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
259 
260             UpdateStatementProvider updateStatement = update(items)
261                     .set(amount).equalTo(add(amount, constant("100")))
262                     .orderBy(amount.descending())
263                     .limit(5)
264                     .build()
265                     .render(RenderingStrategies.MYBATIS3);
266 
267             String expected = "update items set amount = (amount + 100) order by amount DESC limit #{parameters.p1}";
268             assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected);
269             assertThat(updateStatement.getParameters()).containsOnly(entry("p1", 5L));
270 
271             int rows = mapper.update(updateStatement);
272             assertThat(rows).isEqualTo(5);
273         }
274     }
275 
276     @Test
277     void testUpdateWithWhereAndLimit() {
278         try (SqlSession session = sqlSessionFactory.openSession()) {
279             CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
280 
281             UpdateStatementProvider updateStatement = update(items)
282                     .set(amount).equalTo(add(amount, constant("100")))
283                     .where(id, isLessThan(10))
284                     .limit(5)
285                     .build()
286                     .render(RenderingStrategies.MYBATIS3);
287 
288             String expected = "update items set amount = (amount + 100) where id < #{parameters.p1,jdbcType=INTEGER} "
289                     + "limit #{parameters.p2}";
290             assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected);
291             assertThat(updateStatement.getParameters()).containsOnly(entry("p1", 10), entry("p2", 5L));
292 
293             int rows = mapper.update(updateStatement);
294             assertThat(rows).isEqualTo(5);
295         }
296     }
297 
298     @Test
299     void testUpdateWithWhereAndOrderBy() {
300         try (SqlSession session = sqlSessionFactory.openSession()) {
301             CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
302 
303             UpdateStatementProvider updateStatement = update(items)
304                     .set(amount).equalTo(add(amount, constant("100")))
305                     .where(id, isLessThan(10))
306                     .orderBy(amount.descending())
307                     .build()
308                     .render(RenderingStrategies.MYBATIS3);
309 
310             String expected = "update items set amount = (amount + 100) where id < #{parameters.p1,jdbcType=INTEGER} "
311                     + "order by amount DESC";
312             assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected);
313             assertThat(updateStatement.getParameters()).containsOnly(entry("p1", 10));
314 
315             int rows = mapper.update(updateStatement);
316             assertThat(rows).isEqualTo(9);
317         }
318     }
319 
320     @Test
321     void testUpdateWithWhereAndOrderByAndLimit() {
322         try (SqlSession session = sqlSessionFactory.openSession()) {
323             CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
324 
325             UpdateStatementProvider updateStatement = update(items)
326                     .set(amount).equalTo(add(amount, constant("100")))
327                     .where(id, isLessThan(10))
328                     .orderBy(amount)
329                     .limit(5)
330                     .build()
331                     .render(RenderingStrategies.MYBATIS3);
332 
333             String expected = "update items set amount = (amount + 100) where id < #{parameters.p1,jdbcType=INTEGER} "
334                     + "order by amount limit #{parameters.p2}";
335             assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected);
336             assertThat(updateStatement.getParameters()).containsOnly(entry("p1", 10), entry("p2", 5L));
337 
338             int rows = mapper.update(updateStatement);
339             assertThat(rows).isEqualTo(5);
340         }
341     }
342 }