classes/hirondelle/web4j/database/TxSimple.java
author Tomas Zeman <tzeman@volny.cz>
Wed, 04 Dec 2013 17:00:31 +0100
changeset 0 3060119b1292
permissions -rw-r--r--
Imported web4j 4.10.0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
     1
package hirondelle.web4j.database;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
     2
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
     3
import java.util.*;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
     4
import java.util.logging.*;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
     5
import java.sql.Connection;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
     6
import hirondelle.web4j.util.Util;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
     7
import hirondelle.web4j.util.Args;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
     8
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
     9
/**
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    10
 Perform the simplest kinds of transactions.
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    11
 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    12
 <P>Executes a number of SQL statements, in the same order as passed to the constructor. 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    13
 Each SQL statement is executed once and only once, without any iteration.
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    14
 Each SQL statement must perform an <tt>INSERT</tt>, <tt>DELETE</tt>, or <tt>UPDATE</tt> operation.
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    15
 No <tt>SELECT</tt>s are allowed.
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    16
 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    17
 <P><span class="highlight">It is likely that a significant fraction (perhaps as high as 50%) of all 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    18
 transactions can be implemented with this class. </span>
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    19
 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    20
 <P>Example use case:
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    21
 <PRE>
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    22
 SqlId[] sqlIds = {ADD_THIS, DELETE_THAT};
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    23
 Object[] params = {blah.getX(), blah.getY(), blah.getZ(), blah.getQ()}; 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    24
 Tx doStuff = new TxSimple(sqlIds, params);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    25
 int numRecordsAffected = doStuff.executeTx();
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    26
 </PRE>
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    27
 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    28
 <P>In this example, <tt>blah</tt> will usually represent a Model Object. The data in <tt>params</tt>
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    29
 is divided up among the various <tt>sqlIds</tt>. (This division is performed internally by this class.) 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    30
 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    31
 <P>This class uses strong ordering conventions. <span class="highlight">The order of 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    32
 items in each array passed to the constructor is very important</span> (see {@link #TxSimple(SqlId[], Object[])}).
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    33
*/
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    34
public final class TxSimple implements Tx {
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    35
  
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    36
  /**
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    37
   Constructor.
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    38
  
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    39
   <P><tt>aAllParams</tt> includes the parameters for all operations, concatenated in a single array. Has at least 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    40
   one member. 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    41
   
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    42
   <P>In general, successive pieces of <tt>aAllParams</tt> are used to populate each corresponding 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    43
   statement, in their order of execution. The order of items is here <em>doubly</em> important: the 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    44
   first N parameters are used against the first SQL statement, the next M parameters are 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    45
   used against the second SQL statement, and so on. (This breakdown is deduced internally.)
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    46
    
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    47
   <P>And as usual, within each subset of <tt>aAllParams</tt> 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    48
   corresponding to an SQL statement, the order of parameters matches the order 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    49
   of <tt>'?'</tt> placeholders appearing in the underlying SQL statement.  
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    50
   
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    51
   @param aSqlIds identifiers for the operations to be performed, <em>in the order of their intended execution</em>. Has 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    52
   at least one member. All of the operations are against the same database.
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    53
   @param aAllParams the parameters for all operations, concatenated in a single array. Has at least 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    54
   one member.  (See above for important requirements on their order.) 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    55
  */
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    56
  public TxSimple(SqlId[] aSqlIds, Object[] aAllParams){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    57
    Args.checkForPositive(aSqlIds.length);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    58
    Args.checkForPositive(aAllParams.length);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    59
    
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    60
    fSqlIds = aSqlIds;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    61
    fParams = aAllParams;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    62
    fParamsForStatement = new LinkedHashMap<SqlId, Object[]>();
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    63
    divideUpParams();
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    64
  }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    65
  
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    66
  public int executeTx() throws DAOException {
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    67
    Tx transaction = new SimpleTransaction(getDbName());
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    68
    return transaction.executeTx();
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    69
  }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    70
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    71
  // PRIVATE //
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    72
  private SqlId[] fSqlIds;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    73
  private Object[] fParams;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    74
  private Map<SqlId, Object[]> fParamsForStatement;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    75
  private static final Object[] EMPTY = new Object[0];
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    76
  private static final Logger fLogger = Util.getLogger(TxSimple.class);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    77
  
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    78
  private final class SimpleTransaction extends TxTemplate {
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    79
    SimpleTransaction(String aDbName){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    80
      super(aDbName);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    81
    }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    82
    public int executeMultipleSqls(Connection aConnection) throws DAOException {
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    83
      int result = 0;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    84
      for (SqlId sqlId : fSqlIds){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    85
        Object[] params = fParamsForStatement.get(sqlId);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    86
        SqlEditor editor = null;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    87
        if( params.length == 0 ){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    88
          editor = SqlEditor.forTx(sqlId, aConnection);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    89
        }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    90
        else {
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    91
          editor = SqlEditor.forTx(sqlId, aConnection, params);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    92
        }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    93
        result = result + editor.editDatabase();
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    94
      }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    95
      return result;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    96
    }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    97
  }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    98
  
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
    99
  private String getDbName() {
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   100
    return fSqlIds[0].getDatabaseName();
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   101
  }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   102
  
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   103
  private void divideUpParams(){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   104
    int startWith = 0;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   105
    int totalNumExpectedParams = 0;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   106
    for (SqlId sqlId : fSqlIds){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   107
      int numExpectedParams = SqlStatement.getNumParameters(sqlId);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   108
      totalNumExpectedParams = totalNumExpectedParams + numExpectedParams;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   109
      chunkParams(startWith, numExpectedParams, sqlId);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   110
      startWith = startWith + numExpectedParams;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   111
    }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   112
    if ( totalNumExpectedParams != fParams.length ){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   113
      throw new IllegalArgumentException(
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   114
        "Size mismatch. Number of parameters passed as data: " + fParams.length + 
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   115
        ".  Number of '?' items appearing in underlying SQL statements: " + totalNumExpectedParams
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   116
      );
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   117
    }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   118
    fLogger.finest("Chunked params " + Util.logOnePerLine(fParamsForStatement));
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   119
  }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   120
  
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   121
  private void chunkParams(int aStartWithIdx, int aNumExpectedParams, SqlId aSqlId){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   122
    int endWithIdx = aStartWithIdx + aNumExpectedParams - 1;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   123
    int maxIdx = fParams.length - 1;
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   124
    fLogger.fine("Chunking params for " + aSqlId +  ". Start with index " + aStartWithIdx + ", end with index " + endWithIdx);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   125
    if( aStartWithIdx > maxIdx ){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   126
      throw new IllegalArgumentException("Error chunking parameter data. Starting-index (" + aStartWithIdx + ") greater than expected maximum (" + maxIdx + "). Mismatch between number of params passed as data, and number of params expected by underlying SQL statements.");
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   127
    }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   128
    if ( endWithIdx > maxIdx ){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   129
      throw new IllegalArgumentException("Error chunking parameter data. Ending-index (" + endWithIdx + ") greater than expected maximum (" + maxIdx + "). Mismatch between number of params passed as data, and number of params expected by underlying SQL statements.");
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   130
    }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   131
    
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   132
    if( aNumExpectedParams == 0 ){
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   133
      fParamsForStatement.put(aSqlId, EMPTY);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   134
    }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   135
    else {
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   136
      List list = Arrays.asList(fParams);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   137
      List sublist = list.subList(aStartWithIdx, endWithIdx + 1);
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   138
      fParamsForStatement.put(aSqlId, sublist.toArray(EMPTY));
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   139
    }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   140
  }
3060119b1292 Imported web4j 4.10.0
Tomas Zeman <tzeman@volny.cz>
parents:
diff changeset
   141
}