001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.persistence.engines.jdbcengine.querygenerator;
051:
052: import java.util.*;
053: import org.jaffa.persistence.engines.jdbcengine.configservice.ClassMetaData;
054: import org.jaffa.persistence.engines.jdbcengine.variants.Variant;
055:
056: /** This class has functions to return SQL Strings used in PreparedStatements.
057: * These Strings are cached for efficiency purposes.
058: */
059: public class PreparedStatementHelper {
060:
061: // the caches
062: private static Map c_insertStatementCache = new WeakHashMap();
063: private static Map c_updateStatementCache = new WeakHashMap();
064: private static Map c_deleteStatementCache = new WeakHashMap();
065: private static Map c_LockStatementCache = new WeakHashMap();
066:
067: // some constants used in the methods.
068: private static final String INSERT_INTO = "INSERT INTO";
069: private static final String VALUES = "VALUES";
070: private static final String UPDATE = "UPDATE";
071: private static final String SET = "SET";
072: private static final String WHERE = "WHERE";
073: private static final String AND = "AND";
074: private static final String DELETE_FROM = "DELETE FROM";
075: private static final String SELECT_STAR_FROM = "SELECT * FROM";
076:
077: /** Returns a SQL String for use in PreparedStatements for inserting records into the table corresponding to the input ClassMetaData object.
078: * This String is cached.
079: * @param classMetaData the meta object, for which the PreparedStatement String is to be generated.
080: * @return a SQL String for use in PreparedStatements for inserting records.
081: */
082: public static String getInsertPreparedStatementString(
083: ClassMetaData classMetaData) {
084: String sql = (String) c_insertStatementCache.get(classMetaData
085: .getClassName());
086: if (sql == null) {
087: StringBuffer buf1 = new StringBuffer();
088: buf1.append('('); // the fieldlist buffer
089: StringBuffer buf2 = new StringBuffer();
090: buf2.append('('); // the Values buffer
091: boolean first = true;
092: for (Iterator i = classMetaData.getNonAutoKeyFieldNames()
093: .keySet().iterator(); i.hasNext();) {
094: if (first) {
095: first = false;
096: } else {
097: buf1.append(',');
098: buf2.append(',');
099: }
100: buf1
101: .append(classMetaData.getSqlName((String) i
102: .next()));
103: buf2.append('?');
104: }
105: for (Iterator i = classMetaData.getAttributes().keySet()
106: .iterator(); i.hasNext();) {
107: if (first) {
108: first = false;
109: } else {
110: buf1.append(',');
111: buf2.append(',');
112: }
113: buf1
114: .append(classMetaData.getSqlName((String) i
115: .next()));
116: buf2.append('?');
117: }
118: buf1.append(')');
119: buf2.append(')');
120:
121: StringBuffer buf = new StringBuffer(INSERT_INTO);
122: buf.append(' ');
123: buf.append(classMetaData.getTable());
124: buf.append(buf1);
125: buf.append(' ');
126: buf.append(VALUES);
127: buf.append(buf2);
128: synchronized (c_insertStatementCache) {
129: //check again before inserting into cache
130: sql = (String) c_insertStatementCache.get(classMetaData
131: .getClassName());
132: if (sql == null) {
133: sql = buf.toString();
134: c_insertStatementCache.put(classMetaData
135: .getClassName(), sql);
136: }
137: }
138: }
139: return sql;
140: }
141:
142: /** Returns a SQL String for use in PreparedStatements for updating records in the table corresponding to the input ClassMetaData object.
143: * This String is cached.
144: * @param classMetaData the meta object, for which the PreparedStatement String is to be generated.
145: * @return a SQL String for use in PreparedStatements for updating records.
146: */
147: public static String getUpdatePreparedStatementString(
148: ClassMetaData classMetaData) {
149: String sql = (String) c_updateStatementCache.get(classMetaData
150: .getClassName());
151: if (sql == null) {
152: StringBuffer buf = new StringBuffer(UPDATE);
153: buf.append(' ');
154: buf.append(classMetaData.getTable());
155: buf.append(' ');
156: buf.append(SET);
157: buf.append(' ');
158:
159: boolean first = true;
160: for (Iterator i = classMetaData.getAttributes().keySet()
161: .iterator(); i.hasNext();) {
162: if (first) {
163: first = false;
164: } else {
165: buf.append(',');
166: }
167: buf.append(classMetaData.getSqlName((String) i.next()));
168: buf.append('=');
169: buf.append('?');
170: }
171:
172: buf.append(' ');
173: buf.append(WHERE);
174: buf.append(' ');
175: first = true;
176: for (Iterator i = classMetaData.getAllKeyFieldNames()
177: .keySet().iterator(); i.hasNext();) {
178: if (first) {
179: first = false;
180: } else {
181: buf.append(' ');
182: buf.append(AND);
183: buf.append(' ');
184: }
185: buf.append(classMetaData.getSqlName((String) i.next()));
186: buf.append('=');
187: buf.append('?');
188: }
189:
190: synchronized (c_updateStatementCache) {
191: //check again before inserting into cache
192: sql = (String) c_updateStatementCache.get(classMetaData
193: .getClassName());
194: if (sql == null) {
195: sql = buf.toString();
196: c_updateStatementCache.put(classMetaData
197: .getClassName(), sql);
198: }
199: }
200: }
201: return sql;
202: }
203:
204: /** Returns a SQL String for use in PreparedStatements for deleting records from the table corresponding to the input ClassMetaData object.
205: * This String is cached.
206: * @param classMetaData the meta object, for which the PreparedStatement String is to be generated.
207: * @return a SQL String for use in PreparedStatements for deleting records.
208: */
209: public static String getDeletePreparedStatementString(
210: ClassMetaData classMetaData) {
211: String sql = (String) c_deleteStatementCache.get(classMetaData
212: .getClassName());
213: if (sql == null) {
214: StringBuffer buf = new StringBuffer(DELETE_FROM);
215: buf.append(' ');
216: buf.append(classMetaData.getTable());
217: buf.append(' ');
218: buf.append(WHERE);
219: buf.append(' ');
220: boolean first = true;
221: for (Iterator i = classMetaData.getAllKeyFieldNames()
222: .keySet().iterator(); i.hasNext();) {
223: if (first) {
224: first = false;
225: } else {
226: buf.append(' ');
227: buf.append(AND);
228: buf.append(' ');
229: }
230: buf.append(classMetaData.getSqlName((String) i.next()));
231: buf.append('=');
232: buf.append('?');
233: }
234:
235: synchronized (c_deleteStatementCache) {
236: //check again before inserting into cache
237: sql = (String) c_deleteStatementCache.get(classMetaData
238: .getClassName());
239: if (sql == null) {
240: sql = buf.toString();
241: c_deleteStatementCache.put(classMetaData
242: .getClassName(), sql);
243: }
244: }
245: }
246: return sql;
247: }
248:
249: /** Returns a SQL String for use in PreparedStatements for locking records in the table corresponding to the input ClassMetaData object.
250: * This String is cached.
251: * @param classMetaData the meta object, for which the PreparedStatement String is to be generated.
252: * @param engineType The engine type as defined in init.xml
253: * @return a SQL String for use in PreparedStatements for locking records.
254: */
255: public static String getLockPreparedStatementString(
256: ClassMetaData classMetaData, String engineType) {
257: String sql = (String) c_LockStatementCache.get(classMetaData
258: .getClassName());
259: if (sql == null) {
260: StringBuffer buf = new StringBuffer(SELECT_STAR_FROM);
261: buf.append(' ');
262: buf.append(classMetaData.getTable());
263: buf.append(' ');
264: // Added for supplying Locking 'Hints' used by SqlServer
265: buf
266: .append(Variant
267: .getProperty(
268: engineType,
269: Variant.PROP_LOCK_CONSTRUCT_IN_FROM_SELECT_STATEMENT));
270: buf.append(' ');
271: buf.append(WHERE);
272: buf.append(' ');
273:
274: boolean first = true;
275: for (Iterator i = classMetaData.getAllKeyFieldNames()
276: .keySet().iterator(); i.hasNext();) {
277: if (first) {
278: first = false;
279: } else {
280: buf.append(AND);
281: buf.append(' ');
282: }
283: buf.append(classMetaData.getSqlName((String) i.next()));
284: buf.append('=');
285: buf.append('?');
286: buf.append(' ');
287: }
288: buf.append(Variant.getProperty(engineType,
289: Variant.PROP_LOCK_CONSTRUCT_IN_SELECT_STATEMENT));
290:
291: synchronized (c_LockStatementCache) {
292: //check again before inserting into cache
293: sql = (String) c_LockStatementCache.get(classMetaData
294: .getClassName());
295: if (sql == null) {
296: sql = buf.toString();
297: c_LockStatementCache.put(classMetaData
298: .getClassName(), sql);
299: }
300: }
301: }
302: return sql;
303: }
304:
305: }
|