001/* 002 * Copyright 2017-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.springframework.batch.item.database.builder; 017 018import java.util.Map; 019 020import org.hibernate.SessionFactory; 021 022import org.springframework.batch.item.database.HibernatePagingItemReader; 023import org.springframework.batch.item.database.orm.HibernateQueryProvider; 024import org.springframework.util.Assert; 025import org.springframework.util.StringUtils; 026 027/** 028 * A builder for the {@link HibernatePagingItemReader}. When configuring, only one of the 029 * following should be provided: 030 * <ul> 031 * <li>{@link #queryString(String)}</li> 032 * <li>{@link #queryName(String)}</li> 033 * <li>{@link #queryProvider(HibernateQueryProvider)}</li> 034 * </ul> 035 * 036 * @author Michael Minella 037 * @author Glenn Renfro 038 * @author Mahmoud Ben Hassine 039 * @since 4.0 040 * @see HibernatePagingItemReader 041 */ 042public class HibernatePagingItemReaderBuilder<T> { 043 044 private int pageSize = 10; 045 046 private Map<String, Object> parameterValues; 047 048 private String queryName; 049 050 private int fetchSize; 051 052 private HibernateQueryProvider<? extends T> queryProvider; 053 054 private String queryString; 055 056 private SessionFactory sessionFactory; 057 058 private boolean statelessSession = true; 059 060 private boolean saveState = true; 061 062 private String name; 063 064 private int maxItemCount = Integer.MAX_VALUE; 065 066 private int currentItemCount; 067 068 /** 069 * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} 070 * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} 071 * for restart purposes. 072 * 073 * @param saveState defaults to true 074 * @return The current instance of the builder. 075 */ 076 public HibernatePagingItemReaderBuilder<T> saveState(boolean saveState) { 077 this.saveState = saveState; 078 079 return this; 080 } 081 082 /** 083 * The name used to calculate the key within the 084 * {@link org.springframework.batch.item.ExecutionContext}. Required if 085 * {@link #saveState(boolean)} is set to true. 086 * 087 * @param name name of the reader instance 088 * @return The current instance of the builder. 089 * @see org.springframework.batch.item.ItemStreamSupport#setName(String) 090 */ 091 public HibernatePagingItemReaderBuilder<T> name(String name) { 092 this.name = name; 093 094 return this; 095 } 096 097 /** 098 * Configure the max number of items to be read. 099 * 100 * @param maxItemCount the max items to be read 101 * @return The current instance of the builder. 102 * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) 103 */ 104 public HibernatePagingItemReaderBuilder<T> maxItemCount(int maxItemCount) { 105 this.maxItemCount = maxItemCount; 106 107 return this; 108 } 109 110 /** 111 * Index for the current item. Used on restarts to indicate where to start from. 112 * 113 * @param currentItemCount current index 114 * @return this instance for method chaining 115 * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) 116 */ 117 public HibernatePagingItemReaderBuilder<T> currentItemCount(int currentItemCount) { 118 this.currentItemCount = currentItemCount; 119 120 return this; 121 } 122 123 /** 124 * The number of records to request per page/query. Defaults to 10. Must be greater 125 * than zero. 126 * 127 * @param pageSize number of items 128 * @return this instance for method chaining 129 * @see HibernatePagingItemReader#setPageSize(int) 130 */ 131 public HibernatePagingItemReaderBuilder<T> pageSize(int pageSize) { 132 this.pageSize = pageSize; 133 134 return this; 135 } 136 137 /** 138 * A map of parameter values to be set on the query. The key of the map is the name 139 * of the parameter to be set with the value being the value to be set. 140 * 141 * @param parameterValues map of values 142 * @return this instance for method chaining 143 * @see HibernatePagingItemReader#setParameterValues(Map) 144 */ 145 public HibernatePagingItemReaderBuilder<T> parameterValues(Map<String, Object> parameterValues) { 146 this.parameterValues = parameterValues; 147 148 return this; 149 } 150 151 /** 152 * The name of the Hibernate named query to be executed for this reader. 153 * 154 * @param queryName name of the query to execute 155 * @return this instance for method chaining 156 * @see HibernatePagingItemReader#setQueryName(String) 157 */ 158 public HibernatePagingItemReaderBuilder<T> queryName(String queryName) { 159 this.queryName = queryName; 160 161 return this; 162 } 163 164 /** 165 * Fetch size used internally by Hibernate to limit amount of data fetched 166 * from database per round trip. 167 * 168 * @param fetchSize number of records 169 * @return this instance for method chaining 170 * @see HibernatePagingItemReader#setFetchSize(int) 171 */ 172 public HibernatePagingItemReaderBuilder<T> fetchSize(int fetchSize) { 173 this.fetchSize = fetchSize; 174 175 return this; 176 } 177 178 /** 179 * A query provider. This should be set only if {@link #queryString(String)} and 180 * {@link #queryName(String)} have not been set. 181 * 182 * @param queryProvider the query provider 183 * @return this instance for method chaining 184 * @see HibernatePagingItemReader#setQueryProvider(HibernateQueryProvider) 185 */ 186 public HibernatePagingItemReaderBuilder<T> queryProvider(HibernateQueryProvider queryProvider) { 187 this.queryProvider = queryProvider; 188 189 return this; 190 } 191 192 /** 193 * The HQL query string to execute. This should only be set if 194 * {@link #queryProvider(HibernateQueryProvider)} and {@link #queryName(String)} have 195 * not been set. 196 * 197 * @param queryString the HQL query 198 * @return this instance for method chaining 199 * @see HibernatePagingItemReader#setQueryString(String) 200 */ 201 public HibernatePagingItemReaderBuilder<T> queryString(String queryString) { 202 this.queryString = queryString; 203 204 return this; 205 } 206 207 /** 208 * The Hibernate {@link SessionFactory} to execute the query against. 209 * 210 * @param sessionFactory the session factory 211 * @return this instance for method chaining 212 * @see HibernatePagingItemReader#setSessionFactory(SessionFactory) 213 */ 214 public HibernatePagingItemReaderBuilder<T> sessionFactory(SessionFactory sessionFactory) { 215 this.sessionFactory = sessionFactory; 216 217 return this; 218 } 219 220 /** 221 * Indicator for whether to use a {@link org.hibernate.StatelessSession} 222 * (<code>true</code>) or a {@link org.hibernate.Session} (<code>false</code>). 223 * 224 * @param useStatelessSession Defaults to false 225 * @return this instance for method chaining 226 * @see HibernatePagingItemReader#setUseStatelessSession(boolean) 227 * @deprecated This method is deprecated in favor of 228 * {@link HibernatePagingItemReaderBuilder#useStatelessSession} and will be 229 * removed in a future version. 230 */ 231 @Deprecated 232 public HibernatePagingItemReaderBuilder<T> useSatelessSession(boolean useStatelessSession) { 233 return useStatelessSession(useStatelessSession); 234 } 235 236 /** 237 * Indicator for whether to use a {@link org.hibernate.StatelessSession} 238 * (<code>true</code>) or a {@link org.hibernate.Session} (<code>false</code>). 239 * 240 * @param useStatelessSession Defaults to false 241 * @return this instance for method chaining 242 * @see HibernatePagingItemReader#setUseStatelessSession(boolean) 243 */ 244 public HibernatePagingItemReaderBuilder<T> useStatelessSession(boolean useStatelessSession) { 245 this.statelessSession = useStatelessSession; 246 247 return this; 248 } 249 250 /** 251 * Returns a fully constructed {@link HibernatePagingItemReader}. 252 * 253 * @return a new {@link HibernatePagingItemReader} 254 */ 255 public HibernatePagingItemReader<T> build() { 256 Assert.notNull(this.sessionFactory, "A SessionFactory must be provided"); 257 Assert.state(this.fetchSize >= 0, "fetchSize must not be negative"); 258 259 if(this.saveState) { 260 Assert.hasText(this.name, 261 "A name is required when saveState is set to true"); 262 } 263 264 if(this.queryProvider == null) { 265 Assert.state(StringUtils.hasText(queryString) ^ StringUtils.hasText(queryName), 266 "queryString or queryName must be set"); 267 } 268 269 HibernatePagingItemReader<T> reader = new HibernatePagingItemReader<>(); 270 271 reader.setSessionFactory(this.sessionFactory); 272 reader.setSaveState(this.saveState); 273 reader.setMaxItemCount(this.maxItemCount); 274 reader.setCurrentItemCount(this.currentItemCount); 275 reader.setName(this.name); 276 reader.setFetchSize(this.fetchSize); 277 reader.setParameterValues(this.parameterValues); 278 reader.setQueryName(this.queryName); 279 reader.setQueryProvider(this.queryProvider); 280 reader.setQueryString(this.queryString); 281 reader.setPageSize(this.pageSize); 282 reader.setUseStatelessSession(this.statelessSession); 283 284 return reader; 285 } 286}