1 package com.explosion.expfmodules.rdbmsconn.dbom.sql;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
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
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
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
137
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
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
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 }