View Javadoc
1   /*
2    *    Copyright 2009-2021 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.apache.ibatis.executor;
17  
18  import static org.junit.jupiter.api.Assertions.assertEquals;
19  import static org.junit.jupiter.api.Assertions.assertNotNull;
20  import static org.junit.jupiter.api.Assertions.assertNull;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Map;
26  
27  import javassist.util.proxy.Proxy;
28  
29  import javax.sql.DataSource;
30  
31  import org.apache.ibatis.BaseDataTest;
32  import org.apache.ibatis.domain.blog.Author;
33  import org.apache.ibatis.domain.blog.Blog;
34  import org.apache.ibatis.domain.blog.Post;
35  import org.apache.ibatis.domain.blog.Section;
36  import org.apache.ibatis.mapping.MappedStatement;
37  import org.apache.ibatis.session.Configuration;
38  import org.apache.ibatis.session.RowBounds;
39  import org.apache.ibatis.transaction.Transaction;
40  import org.apache.ibatis.transaction.jdbc.JdbcTransaction;
41  import org.junit.jupiter.api.BeforeAll;
42  import org.junit.jupiter.api.Test;
43  
44  class BaseExecutorTest extends BaseDataTest {
45    protected final Configuration config;
46    private static DataSource ds;
47  
48    @BeforeAll
49    static void setup() throws Exception {
50      ds = createBlogDataSource();
51    }
52  
53    BaseExecutorTest() {
54      config = new Configuration();
55      config.setLazyLoadingEnabled(true);
56      config.setUseGeneratedKeys(false);
57      config.setMultipleResultSetsEnabled(true);
58      config.setUseColumnLabel(true);
59      config.setDefaultStatementTimeout(5000);
60      config.setDefaultFetchSize(100);
61    }
62  
63    @Test
64    void shouldInsertNewAuthorWithBeforeAutoKey() throws Exception {
65  
66      Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
67      try {
68        Author author = new Author(-1, "someone", "******", "someone@apache.org", null, Section.NEWS);
69        MappedStatement insertStatement = ExecutorTestHelper.prepareInsertAuthorMappedStatementWithBeforeAutoKey(config);
70        MappedStatement selectStatement = ExecutorTestHelper.prepareSelectOneAuthorMappedStatement(config);
71        int rows = executor.update(insertStatement, author);
72        assertTrue(rows > 0 || rows == BatchExecutor.BATCH_UPDATE_RETURN_VALUE);
73        if (rows == BatchExecutor.BATCH_UPDATE_RETURN_VALUE) {
74          executor.flushStatements();
75        }
76        assertEquals(123456, author.getId());
77        if (author.getId() != BatchExecutor.BATCH_UPDATE_RETURN_VALUE) {
78          List<Author> authors = executor.query(selectStatement, author.getId(), RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
79          executor.rollback(true);
80          assertEquals(1, authors.size());
81          assertEquals(author.toString(), authors.get(0).toString());
82          assertTrue(author.getId() >= 10000);
83        }
84      } finally {
85        executor.rollback(true);
86        executor.close(false);
87      }
88    }
89  
90    @Test
91    void shouldInsertNewAuthor() throws Exception {
92  
93      Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
94      try {
95        Author author = new Author(99, "someone", "******", "someone@apache.org", null, Section.NEWS);
96        MappedStatement insertStatement = ExecutorTestHelper.prepareInsertAuthorMappedStatement(config);
97        MappedStatement selectStatement = ExecutorTestHelper.prepareSelectOneAuthorMappedStatement(config);
98        int rows = executor.update(insertStatement, author);
99        List<Author> authors = executor.query(selectStatement, 99, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
100       executor.flushStatements();
101       executor.rollback(true);
102       assertEquals(1, authors.size());
103       assertEquals(author.toString(), authors.get(0).toString());
104       assertTrue(1 == rows || BatchExecutor.BATCH_UPDATE_RETURN_VALUE == rows);
105     } finally {
106       executor.rollback(true);
107       executor.close(false);
108     }
109   }
110 
111   @Test
112   void shouldSelectAllAuthorsAutoMapped() throws Exception {
113 
114     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
115     try {
116       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectAllAuthorsAutoMappedStatement(config);
117       List<Author> authors = executor.query(selectStatement, null, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
118       assertEquals(2, authors.size());
119       Author author = authors.get(0);
120       // id,username, password, email, bio, favourite_section
121       // (101,'jim','********','jim@ibatis.apache.org','','NEWS');
122       assertEquals(101, author.getId());
123       assertEquals("jim", author.getUsername());
124       assertEquals("jim@ibatis.apache.org", author.getEmail());
125       assertEquals("", author.getBio());
126       assertEquals(Section.NEWS, author.getFavouriteSection());
127     } finally {
128       executor.rollback(true);
129       executor.close(false);
130     }
131   }
132 
133   @Test
134   void shouldInsertNewAuthorWithAutoKey() throws Exception {
135 
136     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
137     try {
138       Author author = new Author(-1, "someone", "******", "someone@apache.org", null, Section.NEWS);
139       MappedStatement insertStatement = ExecutorTestHelper.prepareInsertAuthorMappedStatementWithAutoKey(config);
140       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectOneAuthorMappedStatement(config);
141       int rows = executor.update(insertStatement, author);
142       assertTrue(rows > 0 || rows == BatchExecutor.BATCH_UPDATE_RETURN_VALUE);
143       if (rows == BatchExecutor.BATCH_UPDATE_RETURN_VALUE) {
144         executor.flushStatements();
145       }
146       assertTrue(-1 != author.getId());
147       if (author.getId() != BatchExecutor.BATCH_UPDATE_RETURN_VALUE) {
148         List<Author> authors = executor.query(selectStatement, author.getId(), RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
149         executor.rollback(true);
150         assertEquals(1, authors.size());
151         assertEquals(author.toString(), authors.get(0).toString());
152         assertTrue(author.getId() >= 10000);
153       }
154     } finally {
155       executor.rollback(true);
156       executor.close(false);
157     }
158   }
159 
160   @Test
161   void shouldInsertNewAuthorByProc() throws Exception {
162 
163     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
164     try {
165       Author author = new Author(97, "someone", "******", "someone@apache.org", null, null);
166       MappedStatement insertStatement = ExecutorTestHelper.prepareInsertAuthorProc(config);
167       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectOneAuthorMappedStatement(config);
168       int rows = executor.update(insertStatement, author);
169       List<Author> authors = executor.query(selectStatement, 97, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
170       executor.flushStatements();
171       executor.rollback(true);
172       assertEquals(1, authors.size());
173       assertEquals(author.toString(), authors.get(0).toString());
174     } finally {
175       executor.rollback(true);
176       executor.close(false);
177     }
178   }
179 
180   @Test
181   void shouldInsertNewAuthorUsingSimpleNonPreparedStatements() throws Exception {
182 
183     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
184     try {
185       Author author = new Author(99, "someone", "******", "someone@apache.org", null, null);
186       MappedStatement insertStatement = ExecutorTestHelper.createInsertAuthorWithIDof99MappedStatement(config);
187       MappedStatement selectStatement = ExecutorTestHelper.createSelectAuthorWithIDof99MappedStatement(config);
188       int rows = executor.update(insertStatement, null);
189       List<Author> authors = executor.query(selectStatement, 99, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
190       executor.flushStatements();
191       executor.rollback(true);
192       assertEquals(1, authors.size());
193       assertEquals(author.toString(), authors.get(0).toString());
194       assertTrue(1 == rows || BatchExecutor.BATCH_UPDATE_RETURN_VALUE == rows);
195     } finally {
196       executor.rollback(true);
197       executor.close(false);
198     }
199   }
200 
201   @Test
202   void shouldUpdateAuthor() throws Exception {
203 
204     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
205     try {
206       Author author = new Author(101, "someone", "******", "someone@apache.org", null, Section.NEWS);
207       MappedStatement updateStatement = ExecutorTestHelper.prepareUpdateAuthorMappedStatement(config);
208       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectOneAuthorMappedStatement(config);
209       int rows = executor.update(updateStatement, author);
210       List<Author> authors = executor.query(selectStatement, 101, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
211       executor.flushStatements();
212       executor.rollback(true);
213       assertEquals(1, authors.size());
214       assertEquals(author.toString(), authors.get(0).toString());
215       assertTrue(1 == rows || BatchExecutor.BATCH_UPDATE_RETURN_VALUE == rows);
216     } finally {
217       executor.rollback(true);
218       executor.close(false);
219     }
220   }
221 
222   @Test
223   void shouldDeleteAuthor() throws Exception {
224 
225     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
226     try {
227       Author author = new Author(101, null, null, null, null, null);
228       MappedStatement deleteStatement = ExecutorTestHelper.prepareDeleteAuthorMappedStatement(config);
229       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectOneAuthorMappedStatement(config);
230       int rows = executor.update(deleteStatement, author);
231       List<Author> authors = executor.query(selectStatement, 101, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
232       executor.flushStatements();
233       executor.rollback(true);
234       assertEquals(0, authors.size());
235       assertTrue(1 == rows || BatchExecutor.BATCH_UPDATE_RETURN_VALUE == rows);
236     } finally {
237       executor.rollback(true);
238       executor.close(false);
239     }
240   }
241 
242   @Test
243   void shouldSelectDiscriminatedPost() throws Exception {
244 
245     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
246     try {
247       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectDiscriminatedPost(config);
248       List<Map<String,String>> products = executor.query(selectStatement, null, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
249       assertEquals(5, products.size());
250       for (Map<String,String> m : products) {
251         if ("IMAGES".equals(m.get("SECTION"))) {
252           assertNull(m.get("subject"));
253         } else {
254           assertNotNull(m.get("subject"));
255         }
256       }
257     } finally {
258       executor.close(false);
259     }
260   }
261 
262   @Test
263   void shouldSelect2DiscriminatedPosts() throws Exception {
264 
265     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
266     try {
267       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectDiscriminatedPost(config);
268       List<Map<String,String>> products = executor.query(selectStatement, null, new RowBounds(2, 2), Executor.NO_RESULT_HANDLER);
269       assertEquals(2, products.size());
270       for (Map<String,String> m : products) {
271         if ("IMAGES".equals(m.get("SECTION"))) {
272           assertNull(m.get("subject"));
273         } else {
274           assertNotNull(m.get("subject"));
275         }
276       }
277     } finally {
278       executor.rollback(true);
279       executor.close(false);
280     }
281   }
282 
283   @Test
284   void shouldSelectTwoSetsOfAuthorsViaProc() throws Exception {
285     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
286     try {
287       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectTwoSetsOfAuthorsProc(config);
288       List<List<Author>> authorSets = executor.query(selectStatement, new HashMap<String, Object>() {
289         {
290           put("id1", 101);
291           put("id2", 102);
292         }
293       }, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
294       assertEquals(2, authorSets.size());
295       for (List<Author> authors : authorSets) {
296         assertEquals(2, authors.size());
297         for (Object author : authors) {
298           assertTrue(author instanceof Author);
299         }
300       }
301     } finally {
302       executor.rollback(true);
303       executor.close(false);
304     }
305   }
306 
307   @Test
308   void shouldSelectAuthorViaOutParams() throws Exception {
309 
310     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
311     try {
312       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectAuthorViaOutParams(config);
313       Author author = new Author(102, null, null, null, null, null);
314       executor.query(selectStatement, author, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
315       assertEquals("sally", author.getUsername());
316       assertEquals("********", author.getPassword());
317       assertEquals("sally@ibatis.apache.org", author.getEmail());
318       assertNull(author.getBio());
319     } catch (ExecutorException e) {
320       if (executor instanceof CachingExecutor) {
321         // TODO see issue #464. Fail is OK.
322         assertTrue(e.getMessage().contains("OUT params is not supported"));
323       } else {
324         throw e;
325       }
326     } finally {
327       executor.rollback(true);
328       executor.close(false);
329     }
330   }
331 
332   @Test
333   void shouldFetchPostsForBlog() throws Exception {
334 
335     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
336     try {
337       MappedStatement selectBlog = ExecutorTestHelper.prepareComplexSelectBlogMappedStatement(config);
338       MappedStatement selectPosts = ExecutorTestHelper.prepareSelectPostsForBlogMappedStatement(config);
339       config.addMappedStatement(selectBlog);
340       config.addMappedStatement(selectPosts);
341       List<Post> posts = executor.query(selectPosts, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
342       executor.flushStatements();
343       assertEquals(2, posts.size());
344       assertTrue(posts.get(1) instanceof Proxy);
345       assertNotNull(posts.get(1).getBlog());
346       assertEquals(1, posts.get(1).getBlog().getId());
347       executor.rollback(true);
348     } finally {
349       executor.rollback(true);
350       executor.close(false);
351     }
352   }
353 
354   @Test
355   void shouldFetchOneOrphanedPostWithNoBlog() throws Exception {
356 
357     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
358     try {
359       MappedStatement selectBlog = ExecutorTestHelper.prepareComplexSelectBlogMappedStatement(config);
360       MappedStatement selectPost = ExecutorTestHelper.prepareSelectPostMappedStatement(config);
361       config.addMappedStatement(selectBlog);
362       config.addMappedStatement(selectPost);
363       List<Post> posts = executor.query(selectPost, 5, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
364       executor.flushStatements();
365       executor.rollback(true);
366       assertEquals(1, posts.size());
367       Post post = posts.get(0);
368       assertNull(post.getBlog());
369     } finally {
370       executor.rollback(true);
371       executor.close(false);
372     }
373   }
374 
375   @Test
376   void shouldFetchPostWithBlogWithCompositeKey() throws Exception {
377 
378     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
379     try {
380       MappedStatement selectBlog = ExecutorTestHelper.prepareSelectBlogByIdAndAuthor(config);
381       MappedStatement selectPost = ExecutorTestHelper.prepareSelectPostWithBlogByAuthorMappedStatement(config);
382       config.addMappedStatement(selectBlog);
383       config.addMappedStatement(selectPost);
384       List<Post> posts = executor.query(selectPost, 2, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
385       executor.flushStatements();
386       assertEquals(1, posts.size());
387       Post post = posts.get(0);
388       assertNotNull(post.getBlog());
389       assertEquals(101, post.getBlog().getAuthor().getId());
390       executor.rollback(true);
391     } finally {
392       executor.rollback(true);
393       executor.close(false);
394     }
395   }
396 
397   @Test
398   void shouldFetchComplexBlogs() throws Exception {
399 
400     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
401     try {
402       MappedStatement selectBlog = ExecutorTestHelper.prepareComplexSelectBlogMappedStatement(config);
403       MappedStatement selectPosts = ExecutorTestHelper.prepareSelectPostsForBlogMappedStatement(config);
404       config.addMappedStatement(selectBlog);
405       config.addMappedStatement(selectPosts);
406       List<Blog> blogs = executor.query(selectBlog, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
407       executor.flushStatements();
408       assertEquals(1, blogs.size());
409       assertNotNull(blogs.get(0).getPosts());
410       assertEquals(2, blogs.get(0).getPosts().size());
411       assertEquals(1, blogs.get(0).getPosts().get(1).getBlog().getPosts().get(1).getBlog().getId());
412       executor.rollback(true);
413     } finally {
414       executor.rollback(true);
415       executor.close(false);
416     }
417   }
418 
419   @Test
420   void shouldMapConstructorResults() throws Exception {
421 
422     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
423     try {
424       MappedStatement selectStatement = ExecutorTestHelper.prepareSelectOneAuthorMappedStatementWithConstructorResults(config);
425       List<Author> authors = executor.query(selectStatement, 102, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
426       executor.flushStatements();
427       executor.rollback(true);
428       assertEquals(1, authors.size());
429 
430       Author author = authors.get(0);
431       assertEquals(102, author.getId());
432     } finally {
433       executor.rollback(true);
434       executor.close(false);
435     }
436   }
437 
438   @Test
439   void shouldClearDeferredLoads() throws Exception {
440 
441     Executor executor = createExecutor(new JdbcTransaction(ds, null, false));
442     try {
443       MappedStatement selectBlog = ExecutorTestHelper.prepareComplexSelectBlogMappedStatement(config);
444       MappedStatement selectPosts = ExecutorTestHelper.prepareSelectPostsForBlogMappedStatement(config);
445       config.addMappedStatement(selectBlog);
446       config.addMappedStatement(selectPosts);
447       MappedStatement selectAuthor = ExecutorTestHelper.prepareSelectOneAuthorMappedStatement(config);
448       MappedStatement insertAuthor = ExecutorTestHelper.prepareInsertAuthorMappedStatement(config);
449 
450       // generate DeferredLoads
451       executor.query(selectPosts, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
452 
453       Author author = new Author(-1, "someone", "******", "someone@apache.org", null, Section.NEWS);
454       executor.update(insertAuthor, author);
455       executor.query(selectAuthor, -1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
456       executor.flushStatements();
457       executor.rollback(true);
458     } finally {
459       executor.rollback(true);
460       executor.close(false);
461     }
462   }
463 
464   protected Executor createExecutor(Transaction transaction) {
465     return new SimpleExecutor(config, transaction);
466   }
467 
468 }