EMMA Coverage Report (generated Thu May 22 12:08:10 CDT 2014)
[all classes][org.springframework.batch.item.database]

COVERAGE SUMMARY FOR SOURCE FILE [JdbcBatchItemWriter.java]

nameclass, %method, %block, %line, %
JdbcBatchItemWriter.java100% (2/2)85%  (11/13)84%  (215/255)87%  (47/54)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JdbcBatchItemWriter100% (1/1)82%  (9/11)82%  (184/224)86%  (42/49)
setAssertUpdates (boolean): void 0%   (0/1)0%   (0/4)0%   (0/2)
setDataSource (DataSource): void 0%   (0/1)0%   (0/10)0%   (0/3)
afterPropertiesSet (): void 100% (1/1)74%  (37/50)91%  (10/11)
write (List): void 100% (1/1)90%  (118/131)95%  (21/22)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
JdbcBatchItemWriter (): void 100% (1/1)100% (6/6)100% (2/2)
access$000 (JdbcBatchItemWriter): ItemPreparedStatementSetter 100% (1/1)100% (3/3)100% (1/1)
setItemPreparedStatementSetter (ItemPreparedStatementSetter): void 100% (1/1)100% (4/4)100% (2/2)
setItemSqlParameterSourceProvider (ItemSqlParameterSourceProvider): void 100% (1/1)100% (4/4)100% (2/2)
setJdbcTemplate (NamedParameterJdbcOperations): void 100% (1/1)100% (4/4)100% (2/2)
setSql (String): void 100% (1/1)100% (4/4)100% (2/2)
     
class JdbcBatchItemWriter$1100% (1/1)100% (2/2)100% (31/31)100% (6/6)
JdbcBatchItemWriter$1 (JdbcBatchItemWriter, List): void 100% (1/1)100% (9/9)100% (1/1)
doInPreparedStatement (PreparedStatement): Object 100% (1/1)100% (22/22)100% (5/5)

1/*
2 * Copyright 2006-2013 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 */
16package org.springframework.batch.item.database;
17 
18import java.sql.PreparedStatement;
19import java.sql.SQLException;
20import java.util.ArrayList;
21import java.util.List;
22import java.util.Map;
23 
24import javax.sql.DataSource;
25 
26import org.apache.commons.logging.Log;
27import org.apache.commons.logging.LogFactory;
28import org.springframework.batch.item.ItemWriter;
29import org.springframework.beans.factory.InitializingBean;
30import org.springframework.dao.DataAccessException;
31import org.springframework.dao.EmptyResultDataAccessException;
32import org.springframework.dao.InvalidDataAccessApiUsageException;
33import org.springframework.jdbc.core.PreparedStatementCallback;
34import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
35import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
36import org.springframework.jdbc.core.namedparam.SqlParameterSource;
37import org.springframework.util.Assert;
38 
39/**
40 * <p>{@link ItemWriter} that uses the batching features from
41 * {@link NamedParameterJdbcTemplate} to execute a batch of statements for all items
42 * provided.</p>
43 *
44 * The user must provide an SQL query and a special callback in the for of either
45 * {@link ItemPreparedStatementSetter}, or a {@link ItemSqlParameterSourceProvider}.
46 * You can use either named parameters or the traditional '?' placeholders. If you use the
47 * named parameter support then you should provide a {@link ItemSqlParameterSourceProvider},
48 * otherwise you should provide a  {@link ItemPreparedStatementSetter}.
49 * This callback would be responsible for mapping the item to the parameters needed to
50 * execute the SQL statement.<br/>
51 *
52 * It is expected that {@link #write(List)} is called inside a transaction.<br/>
53 *
54 * The writer is thread safe after its properties are set (normal singleton
55 * behavior), so it can be used to write in multiple concurrent transactions.
56 *
57 * @author Dave Syer
58 * @author Thomas Risberg
59 * @author Michael Minella
60 * @since 2.0
61 */
62public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
63 
64        protected static final Log logger = LogFactory.getLog(JdbcBatchItemWriter.class);
65 
66        private NamedParameterJdbcOperations namedParameterJdbcTemplate;
67 
68        private ItemPreparedStatementSetter<T> itemPreparedStatementSetter;
69 
70        private ItemSqlParameterSourceProvider<T> itemSqlParameterSourceProvider;
71 
72        private String sql;
73 
74        private boolean assertUpdates = true;
75 
76        private int parameterCount;
77 
78        private boolean usingNamedParameters;
79 
80        /**
81         * Public setter for the flag that determines whether an assertion is made
82         * that all items cause at least one row to be updated.
83         * @param assertUpdates the flag to set. Defaults to true;
84         */
85        public void setAssertUpdates(boolean assertUpdates) {
86                this.assertUpdates = assertUpdates;
87        }
88 
89        /**
90         * Public setter for the query string to execute on write. The parameters
91         * should correspond to those known to the
92         * {@link ItemPreparedStatementSetter}.
93         * @param sql the query to set
94         */
95        public void setSql(String sql) {
96                this.sql = sql;
97        }
98 
99        /**
100         * Public setter for the {@link ItemPreparedStatementSetter}.
101         * @param preparedStatementSetter the {@link ItemPreparedStatementSetter} to
102         * set. This is required when using traditional '?' placeholders for the SQL statement.
103         */
104        public void setItemPreparedStatementSetter(ItemPreparedStatementSetter<T> preparedStatementSetter) {
105                this.itemPreparedStatementSetter = preparedStatementSetter;
106        }
107 
108        /**
109         * Public setter for the {@link ItemSqlParameterSourceProvider}.
110         * @param itemSqlParameterSourceProvider the {@link ItemSqlParameterSourceProvider} to
111         * set. This is required when using named parameters for the SQL statement and the type
112         * to be written does not implement {@link Map}.
113         */
114        public void setItemSqlParameterSourceProvider(ItemSqlParameterSourceProvider<T> itemSqlParameterSourceProvider) {
115                this.itemSqlParameterSourceProvider = itemSqlParameterSourceProvider;
116        }
117 
118        /**
119         * Public setter for the data source for injection purposes.
120         *
121         * @param dataSource
122         */
123        public void setDataSource(DataSource dataSource) {
124                if (namedParameterJdbcTemplate == null) {
125                        this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
126                }
127        }
128 
129        /**
130         * Public setter for the {@link NamedParameterJdbcOperations}.
131         * @param namedParameterJdbcTemplate the {@link NamedParameterJdbcOperations} to set
132         */
133        public void setJdbcTemplate(NamedParameterJdbcOperations namedParameterJdbcTemplate) {
134                this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
135        }
136 
137        /**
138         * Check mandatory properties - there must be a SimpleJdbcTemplate and an SQL statement plus a
139         * parameter source.
140         */
141        @Override
142        public void afterPropertiesSet() {
143                Assert.notNull(namedParameterJdbcTemplate, "A DataSource or a NamedParameterJdbcTemplate is required.");
144                Assert.notNull(sql, "An SQL statement is required.");
145                List<String> namedParameters = new ArrayList<String>();
146                parameterCount = JdbcParameterUtils.countParameterPlaceholders(sql, namedParameters);
147                if (namedParameters.size() > 0) {
148                        if (parameterCount != namedParameters.size()) {
149                                throw new InvalidDataAccessApiUsageException("You can't use both named parameters and classic \"?\" placeholders: " + sql);
150                        }
151                        usingNamedParameters = true;
152                }
153                if (!usingNamedParameters) {
154                        Assert.notNull(itemPreparedStatementSetter, "Using SQL statement with '?' placeholders requires an ItemPreparedStatementSetter");
155                }
156        }
157 
158        /* (non-Javadoc)
159         * @see org.springframework.batch.item.ItemWriter#write(java.util.List)
160         */
161        @Override
162        @SuppressWarnings({"unchecked", "rawtypes"})
163        public void write(final List<? extends T> items) throws Exception {
164 
165                if (!items.isEmpty()) {
166 
167                        if (logger.isDebugEnabled()) {
168                                logger.debug("Executing batch with " + items.size() + " items.");
169                        }
170 
171                        int[] updateCounts = null;
172 
173                        if (usingNamedParameters) {
174                                if(items.get(0) instanceof Map) {
175                                        updateCounts = namedParameterJdbcTemplate.batchUpdate(sql, items.toArray(new Map[0]));
176                                } else {
177                                        SqlParameterSource[] batchArgs = new SqlParameterSource[items.size()];
178                                        int i = 0;
179                                        for (T item : items) {
180                                                batchArgs[i++] = itemSqlParameterSourceProvider.createSqlParameterSource(item);
181                                        }
182                                        updateCounts = namedParameterJdbcTemplate.batchUpdate(sql, batchArgs);
183                                }
184                        }
185                        else {
186                                updateCounts = (int[]) namedParameterJdbcTemplate.getJdbcOperations().execute(sql, new PreparedStatementCallback() {
187                                        @Override
188                                        public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
189                                                for (T item : items) {
190                                                        itemPreparedStatementSetter.setValues(item, ps);
191                                                        ps.addBatch();
192                                                }
193                                                return ps.executeBatch();
194                                        }
195                                });
196                        }
197 
198                        if (assertUpdates) {
199                                for (int i = 0; i < updateCounts.length; i++) {
200                                        int value = updateCounts[i];
201                                        if (value == 0) {
202                                                throw new EmptyResultDataAccessException("Item " + i + " of " + updateCounts.length
203                                                                + " did not update any rows: [" + items.get(i) + "]", 1);
204                                        }
205                                }
206                        }
207                }
208        }
209}

[all classes][org.springframework.batch.item.database]
EMMA 2.0.5312 (C) Vladimir Roubtsov