View Javadoc
1   /*
2    * Copyright 2010-2022 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 org.mybatis.spring.batch;
17  
18  import static org.springframework.util.Assert.notNull;
19  import static org.springframework.util.ClassUtils.getShortName;
20  
21  import java.util.HashMap;
22  import java.util.Map;
23  import java.util.Optional;
24  import java.util.concurrent.CopyOnWriteArrayList;
25  import java.util.function.Supplier;
26  
27  import org.apache.ibatis.session.ExecutorType;
28  import org.apache.ibatis.session.SqlSession;
29  import org.apache.ibatis.session.SqlSessionFactory;
30  import org.mybatis.spring.SqlSessionTemplate;
31  import org.springframework.batch.item.database.AbstractPagingItemReader;
32  
33  /**
34   * {@code org.springframework.batch.item.ItemReader} for reading database records using MyBatis in a paging fashion.
35   * <p>
36   * Provided to facilitate the migration from Spring-Batch iBATIS 2 page item readers to MyBatis 3.
37   *
38   * @author Eduardo Macarron
39   *
40   * @since 1.1.0
41   */
42  public class MyBatisPagingItemReader<T> extends AbstractPagingItemReader<T> {
43  
44    private String queryId;
45  
46    private SqlSessionFactory sqlSessionFactory;
47  
48    private SqlSessionTemplate sqlSessionTemplate;
49  
50    private Map<String, Object> parameterValues;
51  
52    private Supplier<Map<String, Object>> parameterValuesSupplier;
53  
54    public MyBatisPagingItemReader() {
55      setName(getShortName(MyBatisPagingItemReader.class));
56    }
57  
58    /**
59     * Public setter for {@link SqlSessionFactory} for injection purposes.
60     *
61     * @param sqlSessionFactory
62     *          a factory object for the {@link SqlSession}.
63     */
64    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
65      this.sqlSessionFactory = sqlSessionFactory;
66    }
67  
68    /**
69     * Public setter for the statement id identifying the statement in the SqlMap configuration file.
70     *
71     * @param queryId
72     *          the id for the statement
73     */
74    public void setQueryId(String queryId) {
75      this.queryId = queryId;
76    }
77  
78    /**
79     * The parameter values to be used for the query execution.
80     *
81     * @param parameterValues
82     *          the values keyed by the parameter named used in the query string.
83     */
84    public void setParameterValues(Map<String, Object> parameterValues) {
85      this.parameterValues = parameterValues;
86    }
87  
88    /**
89     * The parameter supplier used to get parameter values for the query execution.
90     *
91     * @param parameterValuesSupplier
92     *          the supplier used to get values keyed by the parameter named used in the query string.
93     *
94     * @since 2.1.0
95     */
96    public void setParameterValuesSupplier(Supplier<Map<String, Object>> parameterValuesSupplier) {
97      this.parameterValuesSupplier = parameterValuesSupplier;
98    }
99  
100   /**
101    * Check mandatory properties.
102    *
103    * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
104    */
105   @Override
106   public void afterPropertiesSet() throws Exception {
107     super.afterPropertiesSet();
108     notNull(sqlSessionFactory, "A SqlSessionFactory is required.");
109     notNull(queryId, "A queryId is required.");
110   }
111 
112   @Override
113   protected void doReadPage() {
114     if (sqlSessionTemplate == null) {
115       sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH);
116     }
117     Map<String, Object> parameters = new HashMap<>();
118     if (parameterValues != null) {
119       parameters.putAll(parameterValues);
120     }
121     Optional.ofNullable(parameterValuesSupplier).map(Supplier::get).ifPresent(parameters::putAll);
122     parameters.put("_page", getPage());
123     parameters.put("_pagesize", getPageSize());
124     parameters.put("_skiprows", getPage() * getPageSize());
125     if (results == null) {
126       results = new CopyOnWriteArrayList<>();
127     } else {
128       results.clear();
129     }
130     results.addAll(sqlSessionTemplate.selectList(queryId, parameters));
131   }
132 
133 }