001/* 002 * Copyright 2016 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.math.BigInteger; 019import java.util.Map; 020import javax.sql.DataSource; 021 022import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider; 023import org.springframework.batch.item.database.ItemPreparedStatementSetter; 024import org.springframework.batch.item.database.ItemSqlParameterSourceProvider; 025import org.springframework.batch.item.database.JdbcBatchItemWriter; 026import org.springframework.batch.item.database.support.ColumnMapItemPreparedStatementSetter; 027import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; 028import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; 029import org.springframework.util.Assert; 030 031/** 032 * A builder implementation for the {@link JdbcBatchItemWriter}. 033 * 034 * @author Michael Minella 035 * @since 4.0 036 * @see JdbcBatchItemWriter 037 */ 038public class JdbcBatchItemWriterBuilder<T> { 039 040 private boolean assertUpdates = true; 041 042 private String sql; 043 044 private ItemPreparedStatementSetter<T> itemPreparedStatementSetter; 045 046 private ItemSqlParameterSourceProvider<T> itemSqlParameterSourceProvider; 047 048 private DataSource dataSource; 049 050 private NamedParameterJdbcOperations namedParameterJdbcTemplate; 051 052 private BigInteger mapped = new BigInteger("0"); 053 054 /** 055 * Configure the {@link DataSource} to be used. 056 * 057 * @param dataSource the DataSource 058 * @return The current instance of the builder for chaining. 059 * @see JdbcBatchItemWriter#setDataSource(DataSource) 060 */ 061 public JdbcBatchItemWriterBuilder<T> dataSource(DataSource dataSource) { 062 this.dataSource = dataSource; 063 064 return this; 065 } 066 067 /** 068 * If set to true, confirms that every insert results in the update of at least one 069 * row in the database. Defaults to true. 070 * 071 * @param assertUpdates boolean indicator 072 * @return The current instance of the builder for chaining 073 * @see JdbcBatchItemWriter#setAssertUpdates(boolean) 074 */ 075 public JdbcBatchItemWriterBuilder<T> assertUpdates(boolean assertUpdates) { 076 this.assertUpdates = assertUpdates; 077 078 return this; 079 } 080 081 /** 082 * Set the SQL statement to be used for each item's updates. This is a required 083 * field. 084 * 085 * @param sql SQL string 086 * @return The current instance of the builder for chaining 087 * @see JdbcBatchItemWriter#setSql(String) 088 */ 089 public JdbcBatchItemWriterBuilder<T> sql(String sql) { 090 this.sql = sql; 091 092 return this; 093 } 094 095 /** 096 * Configures a {@link ItemPreparedStatementSetter} for use by the writer. This 097 * should only be used if {@link #columnMapped()} isn't called. 098 * 099 * @param itemPreparedStatementSetter The {@link ItemPreparedStatementSetter} 100 * @return The current instance of the builder for chaining 101 * @see JdbcBatchItemWriter#setItemPreparedStatementSetter(ItemPreparedStatementSetter) 102 */ 103 public JdbcBatchItemWriterBuilder<T> itemPreparedStatementSetter(ItemPreparedStatementSetter<T> itemPreparedStatementSetter) { 104 this.itemPreparedStatementSetter = itemPreparedStatementSetter; 105 106 return this; 107 } 108 109 /** 110 * Configures a {@link ItemSqlParameterSourceProvider} for use by the writer. This 111 * should only be used if {@link #beanMapped()} isn't called. 112 * 113 * @param itemSqlParameterSourceProvider The {@link ItemSqlParameterSourceProvider} 114 * @return The current instance of the builder for chaining 115 * @see JdbcBatchItemWriter#setItemSqlParameterSourceProvider(ItemSqlParameterSourceProvider) 116 */ 117 public JdbcBatchItemWriterBuilder<T> itemSqlParameterSourceProvider(ItemSqlParameterSourceProvider<T> itemSqlParameterSourceProvider) { 118 this.itemSqlParameterSourceProvider = itemSqlParameterSourceProvider; 119 120 return this; 121 } 122 123 /** 124 * The {@link NamedParameterJdbcOperations} instance to use. If one isn't provided, 125 * a {@link DataSource} is required. 126 * 127 * @param namedParameterJdbcOperations The template 128 * @return The current instance of the builder for chaining 129 */ 130 public JdbcBatchItemWriterBuilder<T> namedParametersJdbcTemplate(NamedParameterJdbcOperations namedParameterJdbcOperations) { 131 this.namedParameterJdbcTemplate = namedParameterJdbcOperations; 132 133 return this; 134 } 135 136 /** 137 * Creates a {@link ColumnMapItemPreparedStatementSetter} to be used as your 138 * {@link ItemPreparedStatementSetter}. 139 * 140 * NOTE: The item type for this {@link org.springframework.batch.item.ItemWriter} must 141 * be castable to <code>Map<String,Object>></code>. 142 * 143 * @return The current instance of the builder for chaining 144 * @see ColumnMapItemPreparedStatementSetter 145 */ 146 public JdbcBatchItemWriterBuilder<T> columnMapped() { 147 this.mapped = this.mapped.setBit(0); 148 149 return this; 150 } 151 152 /** 153 * Creates a {@link BeanPropertyItemSqlParameterSourceProvider} to be used as your 154 * {@link ItemSqlParameterSourceProvider}. 155 * 156 * @return The current instance of the builder for chaining 157 * @see BeanPropertyItemSqlParameterSourceProvider 158 */ 159 public JdbcBatchItemWriterBuilder<T> beanMapped() { 160 this.mapped = this.mapped.setBit(1); 161 162 return this; 163 } 164 165 /** 166 * Validates configuration and builds the {@link JdbcBatchItemWriter}. 167 * 168 * @return a {@link JdbcBatchItemWriter} 169 */ 170 @SuppressWarnings("unchecked") 171 public JdbcBatchItemWriter<T> build() { 172 Assert.state(this.dataSource != null || this.namedParameterJdbcTemplate != null, 173 "Either a DataSource or a NamedParameterJdbcTemplate is required"); 174 175 Assert.notNull(this.sql, "A SQL statement is required"); 176 int mappedValue = this.mapped.intValue(); 177 Assert.state(mappedValue != 3, 178 "Either an item can be mapped via db column or via bean spec, can't be both"); 179 180 JdbcBatchItemWriter<T> writer = new JdbcBatchItemWriter<>(); 181 writer.setSql(this.sql); 182 writer.setAssertUpdates(this.assertUpdates); 183 writer.setItemSqlParameterSourceProvider(this.itemSqlParameterSourceProvider); 184 writer.setItemPreparedStatementSetter(this.itemPreparedStatementSetter); 185 186 if(mappedValue == 1) { 187 ((JdbcBatchItemWriter<Map<String,Object>>)writer).setItemPreparedStatementSetter(new ColumnMapItemPreparedStatementSetter()); 188 } else if(mappedValue == 2) { 189 writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()); 190 } 191 192 if(this.dataSource != null) { 193 this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(this.dataSource); 194 } 195 196 writer.setJdbcTemplate(this.namedParameterJdbcTemplate); 197 198 return writer; 199 } 200}