~mortenoh/+junk/dhis2-detailed-import-export

« back to all changes in this revision

Viewing changes to dhis-2/dhis-services/dhis-service-jdbc/src/main/java/org/hisp/dhis/jdbc/batchhandler/AbstractBatchHandler.java

  • Committer: larshelge at gmail
  • Date: 2009-03-03 16:46:36 UTC
  • Revision ID: larshelge@gmail.com-20090303164636-2sjlrquo7ib1gf7r
Initial check-in

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.hisp.dhis.jdbc.batchhandler;
 
2
 
 
3
/*
 
4
 * Copyright (c) 2004-2007, University of Oslo
 
5
 * All rights reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions are met:
 
9
 * * Redistributions of source code must retain the above copyright notice, this
 
10
 *   list of conditions and the following disclaimer.
 
11
 * * Redistributions in binary form must reproduce the above copyright notice,
 
12
 *   this list of conditions and the following disclaimer in the documentation
 
13
 *   and/or other materials provided with the distribution.
 
14
 * * Neither the name of the HISP project nor the names of its contributors may
 
15
 *   be used to endorse or promote products derived from this software without
 
16
 *   specific prior written permission.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
21
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 
22
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 
25
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
28
 */
 
29
 
 
30
import java.sql.Connection;
 
31
import java.sql.DriverManager;
 
32
import java.sql.ResultSet;
 
33
import java.sql.SQLException;
 
34
import java.sql.Statement;
 
35
import java.util.ArrayList;
 
36
import java.util.Collection;
 
37
 
 
38
import org.apache.commons.logging.Log;
 
39
import org.apache.commons.logging.LogFactory;
 
40
import org.hisp.dhis.jdbc.BatchHandler;
 
41
import org.hisp.dhis.jdbc.JDBCConfiguration;
 
42
import org.hisp.dhis.jdbc.StatementBuilder;
 
43
import org.hisp.dhis.jdbc.factory.IdentifierExtractorFactory;
 
44
import org.hisp.dhis.jdbc.factory.StatementBuilderFactory;
 
45
import org.hisp.dhis.jdbc.identifier.IdentifierExtractor;
 
46
 
 
47
/**
 
48
 * @author Lars Helge Overland
 
49
 * @version $Id: AbstractBatchHandler.java 5808 2008-10-03 15:18:48Z larshelg $
 
50
 */
 
51
public abstract class AbstractBatchHandler
 
52
    implements BatchHandler
 
53
{
 
54
    private static final Log log = LogFactory.getLog( AbstractBatchHandler.class );
 
55
    
 
56
    private JDBCConfiguration configuration;
 
57
    
 
58
    private Connection connection;
 
59
    
 
60
    private Statement statement;
 
61
    
 
62
    protected StatementBuilder statementBuilder;
 
63
    
 
64
    private IdentifierExtractor identifierExtractor;
 
65
    
 
66
    protected StringBuffer sqlBuffer;
 
67
    
 
68
    private final int maxLength = 200000;
 
69
    
 
70
    private int statementCount = 0;
 
71
    
 
72
    private Collection<Integer> identifiers;
 
73
 
 
74
    protected boolean hasSinglePrimaryKey = true; // Should be overriden by subclasses
 
75
    
 
76
    protected String tableName;
 
77
    
 
78
    // -------------------------------------------------------------------------
 
79
    // Constructor
 
80
    // -------------------------------------------------------------------------
 
81
    
 
82
    @SuppressWarnings( "unused" )
 
83
    private AbstractBatchHandler()
 
84
    {   
 
85
    }
 
86
    
 
87
    protected AbstractBatchHandler( JDBCConfiguration configuration )
 
88
    {
 
89
        this.configuration = configuration;
 
90
        this.statementBuilder = StatementBuilderFactory.createStatementBuilder( configuration.getDialect() );
 
91
        this.identifierExtractor = IdentifierExtractorFactory.createIdentifierExtractor( configuration.getDialect() );
 
92
        
 
93
        setTableName();
 
94
    }
 
95
 
 
96
    // -------------------------------------------------------------------------
 
97
    // BatchHandler implementation
 
98
    // -------------------------------------------------------------------------
 
99
    
 
100
    public void init()
 
101
    {
 
102
        try
 
103
        {
 
104
            Class.forName( configuration.getDriverClass() );
 
105
            
 
106
            connection = DriverManager.getConnection( 
 
107
                configuration.getConnectionUrl(),
 
108
                configuration.getUsername(),
 
109
                configuration.getPassword() );
 
110
            
 
111
            statement = connection.createStatement();
 
112
            
 
113
            sqlBuffer = new StringBuffer( maxLength );
 
114
            
 
115
            statementCount = 0;
 
116
            
 
117
            identifiers = new ArrayList<Integer>();
 
118
            
 
119
            openSqlStatement();
 
120
        }
 
121
        catch ( Exception ex )
 
122
        {
 
123
            throw new RuntimeException( "Failed to create statement", ex );
 
124
        }
 
125
    }
 
126
    
 
127
    public final int insertObject( Object object, boolean returnGeneratedIdentifier )
 
128
    {
 
129
        try
 
130
        {
 
131
            sqlBuffer = new StringBuffer();
 
132
            
 
133
            statementCount = 0;
 
134
            
 
135
            openSqlStatement();
 
136
            
 
137
            addSqlStatement( object );
 
138
            
 
139
            sqlBuffer.deleteCharAt( sqlBuffer.length() - 1 ); 
 
140
            
 
141
            statement.executeUpdate( sqlBuffer.toString() );
 
142
            
 
143
            return returnGeneratedIdentifier ? identifierExtractor.extract( statement ) : 0;
 
144
        }
 
145
        catch ( SQLException ex )
 
146
        {
 
147
            throw new RuntimeException( "Failed to insert " + object.getClass().getName(), ex );
 
148
        }
 
149
    }
 
150
    
 
151
    public final void addObject( Object object )
 
152
    {
 
153
        addSqlStatement( object );
 
154
        
 
155
        statementCount++;
 
156
        
 
157
        if ( sqlBuffer.length() >= maxLength )
 
158
        {
 
159
            try
 
160
            {   
 
161
                sqlBuffer.deleteCharAt( sqlBuffer.length() - 1 );
 
162
                
 
163
                statement.executeUpdate( sqlBuffer.toString() );
 
164
                
 
165
                if ( hasSinglePrimaryKey )
 
166
                {
 
167
                    identifiers.addAll( identifierExtractor.extract( statement, statementCount ) );
 
168
                }
 
169
                
 
170
                sqlBuffer = new StringBuffer();
 
171
                
 
172
                statementCount = 0;
 
173
                
 
174
                openSqlStatement();
 
175
            }
 
176
            catch ( SQLException ex )
 
177
            {
 
178
                log.debug( "SQL statement leading to exception: '" + sqlBuffer.toString() + "'" );
 
179
                
 
180
                throw new RuntimeException( "Failed to add objects", ex );
 
181
            }
 
182
        }
 
183
    }
 
184
    
 
185
    public final void updateObject( Object object )
 
186
    {
 
187
        try
 
188
        {
 
189
            String sql = getUpdateSqlStatement( object );
 
190
            
 
191
            statement.executeUpdate( sql );
 
192
        }
 
193
        catch ( SQLException ex )
 
194
        {
 
195
            throw new RuntimeException( "Failed to update object", ex );
 
196
        }
 
197
    }
 
198
 
 
199
    public final boolean objectExists( Object objectName )
 
200
    {
 
201
        try
 
202
        {
 
203
            String sql = getUniquenessStatement( objectName );
 
204
            
 
205
            ResultSet resultSet = statement.executeQuery( sql );   
 
206
            
 
207
            return resultSet.next();
 
208
        }
 
209
        catch ( SQLException ex )
 
210
        {
 
211
            throw new RuntimeException( "Failed to check uniqueness of object", ex );            
 
212
        }
 
213
    }
 
214
    
 
215
    public int getObjectIdentifier( Object objectName )
 
216
    {
 
217
        try
 
218
        {
 
219
            String sql = getIdentifierStatement( objectName );
 
220
            
 
221
            ResultSet resultSet = statement.executeQuery( sql );  
 
222
            
 
223
            return resultSet.next() ? resultSet.getInt( 1 ) : 0;
 
224
        }
 
225
        catch ( SQLException ex )
 
226
        {
 
227
            throw new RuntimeException( "Failed to get object identifier", ex );            
 
228
        }        
 
229
    }
 
230
    
 
231
    public final Collection<Integer> flush()
 
232
    {
 
233
        try
 
234
        {
 
235
            if ( sqlBuffer.length() > 2 && statementCount != 0 )
 
236
            {
 
237
                sqlBuffer.deleteCharAt( sqlBuffer.length() - 1 );
 
238
                
 
239
                statement.executeUpdate( sqlBuffer.toString() );
 
240
                
 
241
                if ( hasSinglePrimaryKey )
 
242
                {
 
243
                    identifiers.addAll( identifierExtractor.extract( statement, statementCount ) );
 
244
                }
 
245
                
 
246
                statementCount = 0;
 
247
            }
 
248
            
 
249
            return identifiers;
 
250
        }
 
251
        catch ( SQLException ex )
 
252
        {
 
253
            log.debug( "SQL statement leading to exception: '" + sqlBuffer.toString() + "'" );
 
254
            
 
255
            throw new RuntimeException( "Failed to flush BatchHandler", ex );
 
256
        }
 
257
        finally
 
258
        {
 
259
            if ( statement != null )
 
260
            {
 
261
                try
 
262
                {
 
263
                    statement.close();
 
264
                }
 
265
                catch ( SQLException statementEx )
 
266
                {
 
267
                    statementEx.printStackTrace();
 
268
                }
 
269
            }
 
270
            
 
271
            if ( connection != null )
 
272
            {
 
273
                try
 
274
                {
 
275
                    connection.close();
 
276
                }
 
277
                catch ( SQLException connectionEx )
 
278
                {
 
279
                    connectionEx.printStackTrace();
 
280
                }
 
281
            }
 
282
        }
 
283
    }
 
284
 
 
285
    // -------------------------------------------------------------------------
 
286
    // Supportive methods
 
287
    // -------------------------------------------------------------------------
 
288
 
 
289
    private void addSqlStatement( Object object )
 
290
    {
 
291
        addValues( object );
 
292
        
 
293
        sqlBuffer.append( statementBuilder.getInsertStatementValues() );
 
294
    }
 
295
 
 
296
    public void setTableName( String tableName )
 
297
    {
 
298
        this.tableName = tableName;
 
299
    }
 
300
    
 
301
    // -------------------------------------------------------------------------
 
302
    // Abstract methods
 
303
    // -------------------------------------------------------------------------
 
304
 
 
305
    protected abstract void setTableName();
 
306
    
 
307
    protected abstract void openSqlStatement();
 
308
    
 
309
    protected abstract String getUpdateSqlStatement( Object object );
 
310
    
 
311
    protected abstract String getIdentifierStatement( Object objectName );
 
312
    
 
313
    protected abstract String getUniquenessStatement( Object object );
 
314
    
 
315
    protected abstract void addColumns();
 
316
    
 
317
    protected abstract void addValues( Object object );
 
318
}