View Javadoc

1   package com.explosion.expfmodules.rdbmsconn.dbom.sql;
2   
3   
4   /* =============================================================================
5    *       
6    *     Copyright 2004 Stephen Cowx
7    *
8    *     Licensed under the Apache License, Version 2.0 (the "License");
9    *     you may not use this file except in compliance with the License.
10   *     You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   *     Unless required by applicable law or agreed to in writing, software
15   *     distributed under the License is distributed on an "AS IS" BASIS,
16   *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   *     See the License for the specific language governing permissions and
18   *     limitations under the License.
19   * 
20   * =============================================================================
21   */
22  
23  import java.sql.DatabaseMetaData;
24  import java.sql.PreparedStatement;
25  import java.sql.SQLException;
26  import java.text.ParseException;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.Map;
30  
31  import org.apache.log4j.LogManager;
32  import org.apache.log4j.Logger;
33  
34  import com.explosion.expfmodules.rdbmsconn.dbom.DBEntity;
35  import com.explosion.expfmodules.rdbmsconn.dbom.DBEntityColumn;
36  import com.explosion.expfmodules.rdbmsconn.dbom.utils.MetadataUtils;
37  import com.explosion.expfmodules.rdbmsconn.dbom.utils.SQLEngine;
38  import com.explosion.expfmodules.rdbmsconn.dbom.utils.UnconvertableDataTypeException;
39  import com.explosion.expfmodules.rdbmsconn.dbom.utils.UnrecognisedTypeException;
40  import com.explosion.expfmodules.rdbmsconn.dbom.utils.UnsupportedTypeException;
41  import com.explosion.utilities.exception.ExceptionManagerFactory;
42  
43  
44  /***
45   * This class represents an SQL insert statement
46   * @author Stephen
47   * Created on Apr 22, 2004
48   */
49  public class UpdateStatement
50  {
51      private DBEntity entity;
52      private static final String BIND_STRING = "?";
53      private List columnsToUpdate;
54      private List primaryKeyColumns;
55      private static Logger log = LogManager.getLogger(UpdateStatement.class);
56      private MetadataUtils utils = new MetadataUtils();
57      
58      /***
59       * @param entity The entity into which the data is being inserted
60       * @param columnsToUpdate A list of columnsToUpdate which will be updated in the database row 
61       * @param entity
62       * @param bindings
63       */
64      public UpdateStatement(DBEntity entity, List columnsToUpdate)
65      {
66          this.entity = entity;
67          this.columnsToUpdate = columnsToUpdate;
68      }
69      
70      /***
71       * Creates and returns the SQL required for a prepared statement 
72       * by creating a delete statement string which reads 
73       * "update full.tablename set full.columnname1 = ?, full.columnname2 = ? where full.columnname = ? and full.col....."
74       * 
75       * It first to looks to see if there are any primary key columnsToUpdate.  If there are,
76       * it will only use those in the where clause.  If there are none, it will use
77       * all of the columnsToUpdate in the table.  
78       * by createing the SQL command string
79       */
80      public String getPreparedStatementString(DatabaseMetaData meta) throws SQLException
81      {
82          try
83          {
84              /* First build up the update part */
85              StringBuffer statement = new StringBuffer("update " + utils.getFullEntityName(entity, meta) + " set ");
86              for (Iterator i = columnsToUpdate.iterator(); i.hasNext();)
87              {
88                  DBEntityColumn column = entity.getColumn((String) i.next());
89  
90                  /* Exclusions and errors */
91                  if (column.isAutoIncrement() || !column.isWritable())
92                      throw new InvalidUpdateException("Cannot update value in column " + utils.getFullColumnName(column.getColumnName(), entity.getEntityName(), meta));
93  
94                  statement.append(column.getColumnName() + " = ?"+ (i.hasNext() ? ", " : ""));
95              }
96  
97              /* Then build up the where part */
98              statement.append(" where ");
99              primaryKeyColumns = entity.getDerivedIdentityColumns();
100             
101             for (Iterator i = primaryKeyColumns.iterator(); i.hasNext();)
102             {
103             	DBEntityColumn column = (DBEntityColumn) i.next();
104             	statement.append(utils.getFullColumnName(column.getColumnName(),entity.getEntityName(), meta) + " = ?" );
105             	if (i.hasNext() )
106             	    statement.append(" and ");  
107             }
108             
109             return statement.toString();
110             
111         } catch (Exception e)
112         {
113             ExceptionManagerFactory.getExceptionManager().manageException(e,"Exception caught while creating update statement.");
114         }   
115         return null;
116     }
117     
118     /***
119      * This method will bind the variables provided to the statement
120      * provided
121      * @param bindVariablesForUpdate A map containing the columnNames (Strings) and the appropriate values for those columns to be updated in the database
122      *                 				e.g. columnName=value.  Value must be an object of the correct type otherwise an error will be thrown when the 
123      *  			               statement gets executed.
124      * @param bindVariablesForSelection A map containing the columnNames (Strings) and the appropriate values required to select the row which is to be updated
125      * @param statement Prepared Statement.  Note: this statement needs to have been prepared from the 
126      * 					string produced from getPreparedStatementString()  method from this instanceof the 
127      *                  class 
128      * @throws UnconvertableDataTypeException
129      * @throws SQLException
130      * @throws ParseException
131      * @throws UnsupportedTypeException
132      * @throws UnrecognisedTypeException
133      */
134     public void bindVariables(Map bindVariablesForUpdate, Map bindVariablesForSelection, PreparedStatement statement) throws UnconvertableDataTypeException, UnrecognisedTypeException, UnsupportedTypeException, SQLException, ParseException
135     {
136         /* Once again, break this up into two sections ,
137          * First bind the update parameters */
138         SQLEngine engine = new SQLEngine();
139         int index = 1;
140         for (int i=0;i<columnsToUpdate.size(); i++)
141         {
142             String columnName = (String) columnsToUpdate.get(i);
143             DBEntityColumn column = entity.getColumn(columnName);
144             engine.bind(bindVariablesForUpdate.get(columnName),statement, column, i+1);
145             index++;
146         }   
147                 
148         /* Then bind the where parameters */
149         for (Iterator i = primaryKeyColumns.iterator(); i.hasNext();)
150         {
151         	DBEntityColumn column = (DBEntityColumn) i.next();
152         	Object data = bindVariablesForSelection.get(column.getColumnName());
153         	engine.bind(data, statement, column, index);
154         }
155         
156     }
157     
158     /***
159      * This method will tell you if the column will be included in an update statement or not
160      * It also outputs a debug level message if not
161      * @param column
162      */
163     public static boolean includeInUpdate(DBEntityColumn column)
164     {
165         boolean include = true;
166         
167         if (column == null)
168             return false;
169         
170         /* Exclusions and errors */
171         if (column.isAutoIncrement())
172         {
173                log.debug("Not adding column " + column.getColumnName()+ " into update statement because it is an autoIncrement column.");
174                include = false;
175         }
176         
177         return include;
178     }    
179 }