EMMA Coverage Report (generated Thu Jan 24 13:37:04 CST 2013)
[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)89%  (216/243)88%  (44/50)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JdbcBatchItemWriter100% (1/1)82%  (9/11)87%  (185/212)87%  (40/46)
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)76%  (42/55)92%  (11/12)
<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)
setSimpleJdbcTemplate (SimpleJdbcOperations): void 100% (1/1)100% (4/4)100% (2/2)
setSql (String): void 100% (1/1)100% (4/4)100% (2/2)
write (List): void 100% (1/1)100% (114/114)100% (18/18)
     
class JdbcBatchItemWriter$1100% (1/1)100% (2/2)100% (31/31)100% (5/5)
JdbcBatchItemWriter$1 (JdbcBatchItemWriter, List): void 100% (1/1)100% (9/9)100% (1/1)
doInPreparedStatement (PreparedStatement): Object 100% (1/1)100% (22/22)100% (4/4)

1/*
2 * Copyright 2006-2008 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;
22 
23import javax.sql.DataSource;
24 
25import org.apache.commons.logging.Log;
26import org.apache.commons.logging.LogFactory;
27import org.springframework.batch.item.ItemWriter;
28import org.springframework.beans.factory.InitializingBean;
29import org.springframework.dao.DataAccessException;
30import org.springframework.dao.EmptyResultDataAccessException;
31import org.springframework.dao.InvalidDataAccessApiUsageException;
32import org.springframework.jdbc.core.JdbcOperations;
33import org.springframework.jdbc.core.PreparedStatementCallback;
34import org.springframework.jdbc.core.namedparam.SqlParameterSource;
35import org.springframework.jdbc.core.simple.SimpleJdbcOperations;
36import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
37import org.springframework.util.Assert;
38 
39/**
40 * <p>{@link ItemWriter} that uses the batching features from 
41 * {@link SimpleJdbcTemplate} 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 * @since 2.0
60 */
61public class JdbcBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
62 
63        protected static final Log logger = LogFactory.getLog(JdbcBatchItemWriter.class);
64 
65        private SimpleJdbcOperations simpleJdbcTemplate;
66 
67        private ItemPreparedStatementSetter<T> itemPreparedStatementSetter;
68 
69        private ItemSqlParameterSourceProvider<T> itemSqlParameterSourceProvider;
70 
71        private String sql;
72 
73        private boolean assertUpdates = true;
74 
75        private int parameterCount;
76 
77        private boolean usingNamedParameters;
78 
79        /**
80         * Public setter for the flag that determines whether an assertion is made
81         * that all items cause at least one row to be updated.
82         * @param assertUpdates the flag to set. Defaults to true;
83         */
84        public void setAssertUpdates(boolean assertUpdates) {
85                this.assertUpdates = assertUpdates;
86        }
87 
88        /**
89         * Public setter for the query string to execute on write. The parameters
90         * should correspond to those known to the
91         * {@link ItemPreparedStatementSetter}.
92         * @param sql the query to set
93         */
94        public void setSql(String sql) {
95                this.sql = sql;
96        }
97 
98        /**
99         * Public setter for the {@link ItemPreparedStatementSetter}.
100         * @param preparedStatementSetter the {@link ItemPreparedStatementSetter} to
101         * set. This is required when using traditional '?' placeholders for the SQL statement.
102         */
103        public void setItemPreparedStatementSetter(ItemPreparedStatementSetter<T> preparedStatementSetter) {
104                this.itemPreparedStatementSetter = preparedStatementSetter;
105        }
106 
107        /**
108         * Public setter for the {@link ItemSqlParameterSourceProvider}.
109         * @param itemSqlParameterSourceProvider the {@link ItemSqlParameterSourceProvider} to
110         * set. This is required when using named parameters for the SQL statement.
111         */
112        public void setItemSqlParameterSourceProvider(ItemSqlParameterSourceProvider<T> itemSqlParameterSourceProvider) {
113                this.itemSqlParameterSourceProvider = itemSqlParameterSourceProvider;
114        }
115 
116        /**
117         * Public setter for the data source for injection purposes.
118         * 
119         * @param dataSource
120         */
121        public void setDataSource(DataSource dataSource) {
122                if (simpleJdbcTemplate == null) {
123                        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
124                }
125        }
126 
127        /**
128         * Public setter for the {@link JdbcOperations}.
129         * @param simpleJdbcTemplate the {@link JdbcOperations} to set
130         */
131        public void setSimpleJdbcTemplate(SimpleJdbcOperations simpleJdbcTemplate) {
132                this.simpleJdbcTemplate = simpleJdbcTemplate;
133        }
134 
135        /**
136         * Check mandatory properties - there must be a SimpleJdbcTemplate and an SQL statement plus a 
137         * parameter source.
138         */
139        public void afterPropertiesSet() {
140                Assert.notNull(simpleJdbcTemplate, "A DataSource or a SimpleJdbcTemplate is required.");
141                Assert.notNull(sql, "An SQL statement is required.");
142                List<String> namedParameters = new ArrayList<String>();
143                parameterCount = JdbcParameterUtils.countParameterPlaceholders(sql, namedParameters);
144                if (namedParameters.size() > 0) {
145                        if (parameterCount != namedParameters.size()) {
146                                throw new InvalidDataAccessApiUsageException("You can't use both named parameters and classic \"?\" placeholders: " + sql);
147                        }
148                        usingNamedParameters = true;
149                }
150                if (usingNamedParameters) {
151                        Assert.notNull(itemSqlParameterSourceProvider, "Using SQL statement with named parameters requires an ItemSqlParameterSourceProvider");
152                }
153                else {
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        public void write(final List<? extends T> items) throws Exception {
162 
163                if (!items.isEmpty()) {
164 
165                        if (logger.isDebugEnabled()) {
166                                logger.debug("Executing batch with " + items.size() + " items.");
167                        }
168 
169                        int[] updateCounts = null;
170                        
171                        if (usingNamedParameters) {
172                                SqlParameterSource[] batchArgs = new SqlParameterSource[items.size()];
173                                int i = 0;
174                                for (T item : items) {
175                                        batchArgs[i++] = itemSqlParameterSourceProvider.createSqlParameterSource(item);
176                                }
177                                updateCounts = simpleJdbcTemplate.batchUpdate(sql, batchArgs);
178                        }
179                        else {
180                                updateCounts = (int[]) simpleJdbcTemplate.getJdbcOperations().execute(sql, new PreparedStatementCallback() {
181                                        public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
182                                                for (T item : items) {
183                                                        itemPreparedStatementSetter.setValues(item, ps);
184                                                        ps.addBatch();
185                                                }
186                                                return ps.executeBatch();
187                                        }
188                                });
189                        }
190 
191                        if (assertUpdates) {
192                                for (int i = 0; i < updateCounts.length; i++) {
193                                        int value = updateCounts[i];
194                                        if (value == 0) {
195                                                throw new EmptyResultDataAccessException("Item " + i + " of " + updateCounts.length
196                                                                + " did not update any rows: [" + items.get(i) + "]", 1);
197                                        }
198                                }
199                        }
200 
201                }
202 
203        }
204 
205}

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