KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dbunit > operation > RefreshOperation


1 /*
2  *
3  * The DbUnit Database Testing Framework
4  * Copyright (C)2002-2004, DbUnit.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */

21
22 package org.dbunit.operation;
23
24 import org.dbunit.DatabaseUnitException;
25 import org.dbunit.database.IDatabaseConnection;
26 import org.dbunit.database.statement.IPreparedBatchStatement;
27 import org.dbunit.database.statement.SimplePreparedStatement;
28 import org.dbunit.dataset.Column;
29 import org.dbunit.dataset.DataSetException;
30 import org.dbunit.dataset.IDataSet;
31 import org.dbunit.dataset.ITable;
32 import org.dbunit.dataset.ITableIterator;
33 import org.dbunit.dataset.ITableMetaData;
34 import org.dbunit.dataset.NoPrimaryKeyException;
35 import org.dbunit.dataset.RowOutOfBoundsException;
36 import org.dbunit.dataset.datatype.DataType;
37
38 import java.sql.PreparedStatement JavaDoc;
39 import java.sql.ResultSet JavaDoc;
40 import java.sql.SQLException JavaDoc;
41 import java.util.BitSet JavaDoc;
42
43 /**
44  * This operation literally refreshes dataset contents into the database. This
45  * means that data of existing rows is updated and non-existing row get
46  * inserted. Any rows which exist in the database but not in dataset stay
47  * unaffected.
48  *
49  * @author Manuel Laflamme
50  * @version $Revision: 1.35 $
51  * @since Feb 19, 2002
52  */

53 public class RefreshOperation extends AbstractOperation
54 {
55     private final InsertOperation _insertOperation;
56     private final UpdateOperation _updateOperation;
57
58     RefreshOperation()
59     {
60         _insertOperation = (InsertOperation)DatabaseOperation.INSERT;
61         _updateOperation = (UpdateOperation)DatabaseOperation.UPDATE;
62     }
63
64     private boolean isEmpty(ITable table) throws DataSetException
65     {
66         return AbstractBatchOperation.isEmpty(table);
67     }
68
69     ////////////////////////////////////////////////////////////////////////////
70
// DatabaseOperation class
71

72     public void execute(IDatabaseConnection connection, IDataSet dataSet)
73             throws DatabaseUnitException, SQLException JavaDoc
74     {
75         
76         // for each table
77
ITableIterator iterator = dataSet.iterator();
78         while (iterator.next())
79         {
80             ITable table = iterator.getTable();
81
82             // Do not process empty table
83
if (isEmpty(table))
84             {
85                 continue;
86             }
87
88             ITableMetaData metaData = getOperationMetaData(connection,
89                     table.getTableMetaData());
90             RowOperation updateRowOperation = createUpdateOperation(connection,
91                     metaData);
92             RowOperation insertRowOperation = new InsertRowOperation(connection,
93                     metaData);
94
95             try
96             {
97                 // refresh all rows
98
for (int i = 0; ; i++)
99                 {
100                     if (!updateRowOperation.execute(table, i))
101                     {
102                         insertRowOperation.execute(table, i);
103                     }
104                 }
105             }
106             catch (RowOutOfBoundsException e)
107             {
108                 // end of table
109
}
110             finally
111             {
112                 // cleanup
113
updateRowOperation.close();
114                 insertRowOperation.close();
115             }
116         }
117
118     }
119
120     private RowOperation createUpdateOperation(IDatabaseConnection connection,
121             ITableMetaData metaData)
122             throws DataSetException, SQLException JavaDoc
123     {
124         // update only if columns are not all primary keys
125
if (metaData.getColumns().length > metaData.getPrimaryKeys().length)
126         {
127             return new UpdateRowOperation(connection, metaData);
128         }
129
130         // otherwise, operation only verify if row exist
131
return new RowExistOperation(connection, metaData);
132     }
133
134     /**
135      * This class represents a operation executed on a single table row.
136      */

137     class RowOperation
138     {
139         protected IPreparedBatchStatement _statement;
140         protected OperationData _operationData;
141         protected BitSet JavaDoc _ignoreMapping;
142
143         /**
144          * Execute this operation on the sepcified table row.
145          * @return <code>true</code> if operation have been executed on the row.
146          */

147         public boolean execute(ITable table, int row)
148                 throws DataSetException, SQLException JavaDoc
149         {
150             Column[] columns = _operationData.getColumns();
151             for (int i = 0; i < columns.length; i++)
152             {
153                 // Bind value only if not in ignore mapping
154
if (_ignoreMapping == null || !_ignoreMapping.get(i))
155                 {
156                     Object JavaDoc value = table.getValue(row, columns[i].getColumnName());
157                     _statement.addValue(value, columns[i].getDataType());
158                 }
159             }
160             _statement.addBatch();
161             int result = _statement.executeBatch();
162             _statement.clearBatch();
163
164             return result == 1;
165         }
166
167         /**
168          * Cleanup this operation state.
169          */

170         public void close() throws SQLException JavaDoc
171         {
172             if (_statement != null)
173             {
174                 _statement.close();
175             }
176         }
177     }
178
179     /**
180      * Insert row operation.
181      */

182     private class InsertRowOperation extends RowOperation
183     {
184         private IDatabaseConnection _connection;
185         private ITableMetaData _metaData;
186
187         public InsertRowOperation(IDatabaseConnection connection,
188                 ITableMetaData metaData)
189                 throws DataSetException, SQLException JavaDoc
190         {
191             _connection = connection;
192             _metaData = metaData;
193         }
194
195         public boolean execute(ITable table, int row)
196                 throws DataSetException, SQLException JavaDoc
197         {
198             // If current row have a diffrent ignore value mapping than
199
// previous one, we generate a new statement
200
if (_ignoreMapping == null ||
201                     !_insertOperation.equalsIgnoreMapping(_ignoreMapping, table, row))
202             {
203                 // Execute and close previous statement
204
if (_statement != null)
205                 {
206                     _statement.close();
207                 }
208
209                 _ignoreMapping = _insertOperation.getIgnoreMapping(table, row);
210                 _operationData = _insertOperation.getOperationData(_metaData,
211                         _ignoreMapping, _connection);
212                 _statement = new SimplePreparedStatement(_operationData.getSql(),
213                         _connection.getConnection());
214             }
215
216             return super.execute(table, row);
217         }
218
219     }
220
221     /**
222      * Update row operation.
223      */

224     private class UpdateRowOperation extends RowOperation
225     {
226         PreparedStatement _countStatement;
227
228         public UpdateRowOperation(IDatabaseConnection connection,
229                 ITableMetaData metaData)
230                 throws DataSetException, SQLException JavaDoc
231         {
232             // setup update statement
233
_operationData = _updateOperation.getOperationData(
234                     metaData, null, connection);
235             _statement = new SimplePreparedStatement(_operationData.getSql(),
236                     connection.getConnection());
237         }
238     }
239
240     /**
241      * This operation verify if a row exists in the database.
242      */

243     private class RowExistOperation extends RowOperation
244     {
245         PreparedStatement _countStatement;
246
247         public RowExistOperation(IDatabaseConnection connection,
248                 ITableMetaData metaData)
249                 throws DataSetException, SQLException JavaDoc
250         {
251             // setup select count statement
252
_operationData = getSelectCountData(metaData, connection);
253             _countStatement = connection.getConnection().prepareStatement(
254                     _operationData.getSql());
255         }
256
257         private OperationData getSelectCountData(
258                 ITableMetaData metaData, IDatabaseConnection connection) throws DataSetException
259         {
260             Column[] primaryKeys = metaData.getPrimaryKeys();
261
262             // cannot construct where clause if no primary key
263
if (primaryKeys.length == 0)
264             {
265                 throw new NoPrimaryKeyException(metaData.getTableName());
266             }
267
268             // select count
269
StringBuffer JavaDoc sqlBuffer = new StringBuffer JavaDoc(128);
270             sqlBuffer.append("select COUNT(*) from ");
271             sqlBuffer.append(getQualifiedName(connection.getSchema(),
272                     metaData.getTableName(), connection));
273
274             // where
275
sqlBuffer.append(" where ");
276             for (int i = 0; i < primaryKeys.length; i++)
277             {
278                 Column column = primaryKeys[i];
279
280                 if (i > 0)
281                 {
282                     sqlBuffer.append(" and ");
283                 }
284                 sqlBuffer.append(column.getColumnName());
285                 sqlBuffer.append(" = ?");
286             }
287
288             return new OperationData(sqlBuffer.toString(), primaryKeys);
289         }
290
291         ////////////////////////////////////////////////////////////////////////
292
// RowOperation class
293

294         /**
295          * Verify if the specified table row exists in the database.
296          * @return <code>true</code> if row exists.
297          */

298         public boolean execute(ITable table, int row)
299                 throws DataSetException, SQLException JavaDoc
300         {
301             Column[] columns = _operationData.getColumns();
302             for (int i = 0; i < columns.length; i++)
303             {
304                 Object JavaDoc value = table.getValue(row, columns[i].getColumnName());
305                 DataType dataType = columns[i].getDataType();
306                 dataType.setSqlValue(value, i + 1, _countStatement);
307             }
308
309             ResultSet JavaDoc resultSet = _countStatement.executeQuery();
310             try
311             {
312                 resultSet.next();
313                 return resultSet.getInt(1) > 0;
314             }
315             finally
316             {
317                 resultSet.close();
318             }
319         }
320
321         public void close() throws SQLException JavaDoc
322         {
323             _countStatement.close();
324         }
325     }
326
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340
341
Popular Tags