0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
0005: *
0006: *
0007: * The contents of this file are subject to the terms of either the GNU
0008: * General Public License Version 2 only ("GPL") or the Common Development
0009: * and Distribution License("CDDL") (collectively, the "License"). You
0010: * may not use this file except in compliance with the License. You can obtain
0011: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
0012: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
0013: * language governing permissions and limitations under the License.
0014: *
0015: * When distributing the software, include this License Header Notice in each
0016: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
0017: * Sun designates this particular file as subject to the "Classpath" exception
0018: * as provided by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the License
0020: * Header, with the fields enclosed by brackets [] replaced by your own
0021: * identifying information: "Portions Copyrighted [year]
0022: * [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * If you wish your version of this file to be governed by only the CDDL or
0027: * only the GPL Version 2, indicate your decision by adding "[Contributor]
0028: * elects to include this software in this distribution under the [CDDL or GPL
0029: * Version 2] license." If you don't indicate a single choice of license, a
0030: * recipient has the option to distribute your version of this file under
0031: * either the CDDL, the GPL Version 2 or to extend the choice of license to
0032: * its licensees as provided above. However, if you add GPL Version 2 code
0033: * and therefore, elected the GPL Version 2 license, then the option applies
0034: * only if the new code is made subject to such option by the copyright
0035: * holder.
0036: */
0037: package oracle.toplink.essentials.descriptors;
0038:
0039: import java.util.*;
0040: import java.io.*;
0041: import oracle.toplink.essentials.queryframework.*;
0042: import oracle.toplink.essentials.expressions.*;
0043: import oracle.toplink.essentials.mappings.*;
0044: import oracle.toplink.essentials.sessions.DatabaseRecord;
0045: import oracle.toplink.essentials.internal.helper.*;
0046: import oracle.toplink.essentials.exceptions.*;
0047: import oracle.toplink.essentials.descriptors.InheritancePolicy;
0048: import oracle.toplink.essentials.internal.sessions.AbstractSession;
0049:
0050: /**
0051: * <p><b>Purpose</b>: The query manager allows for the database opperations that TopLink
0052: * performs to be customized by the application. For each descriptor a query can be
0053: * given that controls how a operation will occur. A common example is if the application
0054: * requires a stored procedure to be used to insert the object, it can override the SQL call
0055: * in the insert query that TopLink will use to insert the object.
0056: * Queries can be customized to extend TopLink behavior, access non-relational data or use stored
0057: * procedures or customized SQL calls.
0058: * <p>
0059: * The queries that can be customized include:
0060: * <ul>
0061: * <li> insertQuery - used to insert the object
0062: * <li> updateQuery - used to update the object
0063: * <li> readObjectQuery - used to read a single object by primary key
0064: * <li> readAllQuery - used to read all of the objects of the class
0065: * <li> doesExistQuery - used to determine whether an insert or update should occur
0066: * <li> deleteQuery - used to delete the object
0067: * </ul>
0068: *
0069: * @see ClassDescriptor
0070: */
0071: public class DescriptorQueryManager implements Cloneable, Serializable {
0072: protected transient InsertObjectQuery insertQuery;
0073: protected transient UpdateObjectQuery updateQuery;
0074: protected transient ReadObjectQuery readObjectQuery;
0075: protected transient ReadAllQuery readAllQuery;
0076: protected transient DeleteObjectQuery deleteQuery;
0077: protected DoesExistQuery doesExistQuery;
0078: protected ClassDescriptor descriptor;
0079: protected boolean hasCustomMultipleTableJoinExpression;
0080: protected transient Expression additionalJoinExpression;
0081: protected transient Expression multipleTableJoinExpression;
0082: protected transient Map queries;
0083: protected transient Map tablesJoinExpressions;
0084:
0085: /**
0086: * INTERNAL:
0087: * Initialize the state of the descriptor query manager
0088: */
0089: public DescriptorQueryManager() {
0090: this .queries = new HashMap(5);
0091: setDoesExistQuery(new DoesExistQuery());// Always has a does exist.
0092: }
0093:
0094: /**
0095: * PUBLIC:
0096: * Add the query to the descriptor queries with the given name
0097: * @param name This is the name of the query. It will be set on the query and used to look it up.
0098: * @param query This is the query that will be added. If the query being added has parameters, the
0099: * existing list of queries will be checked for matching queries. If a matching query exists,
0100: * it will be replaced.
0101: */
0102: public void addQuery(String name, DatabaseQuery query) {
0103: query.setName(name);
0104: addQuery(query);
0105: }
0106:
0107: /**
0108: * PUBLIC:
0109: * Add the query to the session queries
0110: * @param query DatabaseQuery This is the query that will be added. If the query being added has parameters, the
0111: * existing list of queries will be checked for matching queries. If a matching query exists,
0112: * it will be replaced.
0113: */
0114: public synchronized void addQuery(DatabaseQuery query) {
0115: if (query instanceof ObjectLevelReadQuery
0116: && (((ObjectLevelReadQuery) query)
0117: .getReferenceClassName() == null)) {
0118: ((ObjectLevelReadQuery) query)
0119: .setReferenceClassName(getDescriptor()
0120: .getJavaClassName());
0121:
0122: // try to set the reference ClassNotFoundException since it should only happen on the MW in which
0123: // case we will lazily initialize the reference class at a later point.
0124: try {
0125: ((ObjectLevelReadQuery) query)
0126: .setReferenceClass(getDescriptor()
0127: .getJavaClass());
0128: } catch (ConversionException exception) {
0129: }
0130:
0131: //this is an optimization
0132: query.setDescriptor(getDescriptor());
0133: }
0134:
0135: // Add query has been synchronized for bug 3355199.
0136: // Additionally code has been added to ensure that the same query is not added twice.
0137: Vector queriesByName = (Vector) getQueries().get(
0138: query.getName());
0139: if (queriesByName == null) {
0140: // lazily create Vector in Hashtable.
0141: queriesByName = oracle.toplink.essentials.internal.helper.NonSynchronizedVector
0142: .newInstance();
0143: getQueries().put(query.getName(), queriesByName);
0144: } else {
0145: int argumentTypesSize = 0;
0146: if (query.getArguments() != null) {
0147: argumentTypesSize = query.getArguments().size();
0148: }
0149: Vector argumentTypes = oracle.toplink.essentials.internal.helper.NonSynchronizedVector
0150: .newInstance(argumentTypesSize);
0151: for (int i = 0; i < argumentTypesSize; i++) {
0152: argumentTypes.addElement(query.getArgumentTypeNames()
0153: .elementAt(i));
0154: }
0155:
0156: // Search for a query with the same parameters and replace it if one is found
0157: for (int i = 0; i < queriesByName.size(); i++) {
0158: DatabaseQuery currentQuery = (DatabaseQuery) queriesByName
0159: .elementAt(i);
0160:
0161: // Here we are checking equality instead of assignability. If you look at getQuery()
0162: // it is the other way around.
0163: // The reason we do this is we are replacing a query and we want to make sure we are
0164: // replacing the exact same one. - TW
0165: if (argumentTypes.equals(currentQuery
0166: .getArgumentTypeNames())) {
0167: queriesByName.remove(i);
0168: queriesByName.add(i, query);
0169: return;
0170: }
0171: }
0172: }
0173: queriesByName.add(query);
0174: }
0175:
0176: /**
0177: * PUBLIC:
0178: * Assume that if the objects primary key does not include null then it must exist.
0179: * This may be used if the application guarantees or does not care about the existence check.
0180: */
0181: public void assumeExistenceForDoesExist() {
0182: getDoesExistQuery().assumeExistenceForDoesExist();
0183: }
0184:
0185: /**
0186: * PUBLIC:
0187: * Assume that the object does not exist. This may be used if the application guarantees or
0188: * does not care about the existence check. This will always force an insert to be called.
0189: */
0190: public void assumeNonExistenceForDoesExist() {
0191: getDoesExistQuery().assumeNonExistenceForDoesExist();
0192: }
0193:
0194: /**
0195: * PUBLIC:
0196: * Default behavior.
0197: * Assume that if the objects primary key does not include null and it
0198: * is in the cache, then is must exist.
0199: */
0200: public void checkCacheForDoesExist() {
0201: getDoesExistQuery().checkCacheForDoesExist();
0202: }
0203:
0204: /**
0205: * PUBLIC:
0206: * Perform does exist check on the database
0207: */
0208: public void checkDatabaseForDoesExist() {
0209: getDoesExistQuery().checkDatabaseForDoesExist();
0210: }
0211:
0212: /**
0213: * INTERNAL:
0214: * Clone the query manager
0215: */
0216: public Object clone() {
0217: DescriptorQueryManager manager = null;
0218: try {
0219: manager = (DescriptorQueryManager) super .clone();
0220: } catch (Exception exception) {
0221: ;
0222: }
0223:
0224: // Bug 3037701 - clone the queries
0225: manager.setQueries(new Hashtable(getQueries().size()));
0226: Iterator iterator = queries.values().iterator();
0227: while (iterator.hasNext()) {
0228: Iterator queriesForKey = ((Vector) iterator.next())
0229: .iterator();
0230: while (queriesForKey.hasNext()) {
0231: DatabaseQuery initialQuery = (DatabaseQuery) queriesForKey
0232: .next();
0233: DatabaseQuery clonedQuery = (DatabaseQuery) initialQuery
0234: .clone();
0235: clonedQuery.setDescriptor(manager.getDescriptor());
0236: manager.addQuery(clonedQuery);
0237: }
0238: }
0239: manager.setDoesExistQuery((DoesExistQuery) getDoesExistQuery()
0240: .clone());
0241: if (getReadAllQuery() != null) {
0242: manager.setReadAllQuery((ReadAllQuery) getReadAllQuery()
0243: .clone());
0244: }
0245: if (getReadObjectQuery() != null) {
0246: manager
0247: .setReadObjectQuery((ReadObjectQuery) getReadObjectQuery()
0248: .clone());
0249: }
0250: if (getUpdateQuery() != null) {
0251: manager.setUpdateQuery((UpdateObjectQuery) getUpdateQuery()
0252: .clone());
0253: }
0254: if (getInsertQuery() != null) {
0255: manager.setInsertQuery((InsertObjectQuery) getInsertQuery()
0256: .clone());
0257: }
0258: if (getDeleteQuery() != null) {
0259: manager.setDeleteQuery((DeleteObjectQuery) getDeleteQuery()
0260: .clone());
0261: }
0262:
0263: return manager;
0264: }
0265:
0266: /**
0267: * PUBLIC:
0268: * Return true if the query is defined on the session
0269: */
0270: public boolean containsQuery(String queryName) {
0271: return queries.containsKey(queryName);
0272: }
0273:
0274: /**
0275: * INTERNAL:
0276: * Convert all the class-name-based settings in this Query Manager to actual class-based
0277: * settings
0278: * This method is implemented by subclasses as necessary.
0279: * @param classLoader
0280: */
0281: public void convertClassNamesToClasses(ClassLoader classLoader) {
0282: Iterator queryVectors = getQueries().values().iterator();
0283: while (queryVectors.hasNext()) {
0284: Iterator queries = ((Vector) queryVectors.next())
0285: .iterator();
0286: ;
0287: while (queries.hasNext()) {
0288: ((DatabaseQuery) queries.next())
0289: .convertClassNamesToClasses(classLoader);
0290: }
0291: }
0292: };
0293:
0294: /**
0295: * ADVANCED:
0296: * Returns the join expression that should be appended to all of the descriptors expressions
0297: * Contains any multiple table or inheritance dependencies
0298: */
0299: public Expression getAdditionalJoinExpression() {
0300: return additionalJoinExpression;
0301: }
0302:
0303: /**
0304: * ADVANCED:
0305: * Return the receiver's delete query.
0306: * This should be an instance of a valid subclass of DeleteObjectQuery.
0307: * If specified this is used by the descriptor to delete itself and its private parts from the database.
0308: * This gives the user the ability to define exactly how to delete the data from the database,
0309: * or access data external from the database or from some other framework.
0310: */
0311: public DeleteObjectQuery getDeleteQuery() {
0312: return deleteQuery;
0313: }
0314:
0315: /**
0316: * ADVANCED:
0317: * Return the receiver's delete SQL string.
0318: * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
0319: * The arguments are translated from the fields of the source row,
0320: * through replacing the field names marked by '#' with the values for those fields.
0321: * <p>
0322: * Example, "delete from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID".
0323: */
0324: public String getDeleteSQLString() {
0325: if (getDeleteQuery() == null) {
0326: return null;
0327: }
0328:
0329: return getDeleteQuery().getSQLString();
0330: }
0331:
0332: /**
0333: * INTERNAL:
0334: * Return the descriptor associated with this descriptor query manager
0335: */
0336: protected ClassDescriptor getDescriptor() {
0337: return descriptor;
0338: }
0339:
0340: /**
0341: * ADVANCED:
0342: * Return the receiver's does exist query.
0343: * This should be an instance of a valid subclass of DoesExistQuery.
0344: * If specified this is used by the descriptor to query existence of an object in the database.
0345: * This gives the user the ability to define exactly how to query existence from the database,
0346: * or access data external from the database or from some other framework.
0347: */
0348: public DoesExistQuery getDoesExistQuery() {
0349: return doesExistQuery;
0350: }
0351:
0352: /**
0353:
0354: * ADVANCED:
0355: * Return the receiver's does exist SQL string.
0356: * This allows the user to override the SQL generated by TopLink, with there own SQL or procedure call.
0357: * The arguments are translated from the fields of the source row, through replacing the field names marked by '#'
0358: * with the values for those fields.
0359: * This must return null if the object does not exist, otherwise return a database row.
0360: * <p>
0361: * Example, "select EMPLOYEE_ID from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID".
0362: */
0363: public String getDoesExistSQLString() {
0364: if (getDoesExistQuery() == null) {
0365: return null;
0366: }
0367:
0368: return getDoesExistQuery().getSQLString();
0369: }
0370:
0371: /**
0372: * INTERNAL:
0373: * This method is explicitly used by the Builder only.
0374: */
0375: public String getExistenceCheck() {
0376: if (getDoesExistQuery().shouldAssumeExistenceForDoesExist()) {
0377: return "Assume existence";
0378: } else if (getDoesExistQuery()
0379: .shouldAssumeNonExistenceForDoesExist()) {
0380: return "Assume non-existence";
0381: } else if (getDoesExistQuery().shouldCheckCacheForDoesExist()) {
0382: return "Check cache";
0383: } else if (getDoesExistQuery()
0384: .shouldCheckDatabaseForDoesExist()) {
0385: return "Check database";
0386: } else {
0387: // Default.
0388: return "Check cache";
0389: }
0390: }
0391:
0392: /**
0393: * ADVANCED:
0394: * Return the receiver's insert query.
0395: * This should be an instance of a valid subclass of InsertObjectQuery.
0396: * If specified this is used by the descriptor to insert itself into the database.
0397: * If the receiver uses sequence numbers, this query must return the updated sequence value.
0398: * This gives the user the ability to define exactly how to insert the data into the database,
0399: * or access data externel from the database or from some other framework.
0400: */
0401: public InsertObjectQuery getInsertQuery() {
0402: return insertQuery;
0403: }
0404:
0405: /**
0406: * ADVANCED:
0407: * Return the receiver's insert SQL string.
0408: * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
0409: * The arguments are translated from the fields of the source row,
0410: * through replacing the field names marked by '#' with the values for those fields.
0411: * <p>
0412: * Example, "insert into EMPLOYEE (F_NAME, L_NAME) values (#F_NAME, #L_NAME)".
0413: */
0414: public String getInsertSQLString() {
0415: if (getInsertQuery() == null) {
0416: return null;
0417: }
0418:
0419: return getInsertQuery().getSQLString();
0420: }
0421:
0422: /**
0423: * ADVANCED:
0424: * This is normally generated for descriptors that have multiple tables.
0425: * However, if the additional table does not reference the primary tables primary key,
0426: * this expression may be set directly.
0427: */
0428: public Expression getMultipleTableJoinExpression() {
0429: return multipleTableJoinExpression;
0430: }
0431:
0432: /**
0433: * PUBLIC:
0434: * Return the pre-defined queries for the descriptor. The Hashtable returned
0435: * contains Vectors of queries.
0436: *
0437: * @see #getAllQueries()
0438: */
0439: public Map getQueries() {
0440: return queries;
0441: }
0442:
0443: /**
0444: * PUBLIC:
0445: * Return the pre-defined queries for the descriptor. The Vector returned
0446: * contains all queries for this descriptor.
0447: *
0448: * @see #getQueries()
0449: */
0450: public Vector getAllQueries() {
0451: Vector allQueries = new Vector();
0452: for (Iterator vectors = getQueries().values().iterator(); vectors
0453: .hasNext();) {
0454: allQueries.addAll((Vector) vectors.next());
0455: }
0456: return allQueries;
0457: }
0458:
0459: /**
0460: * INTERNAL:
0461: * Set pre-defined queries for the descriptor. Converts the Vector to a hashtable
0462: */
0463: public void setAllQueries(Vector vector) {
0464: for (Enumeration enumtr = vector.elements(); enumtr
0465: .hasMoreElements();) {
0466: addQuery((DatabaseQuery) enumtr.nextElement());
0467: }
0468: }
0469:
0470: /**
0471: * PUBLIC:
0472: * set the pre-defined queries for the descriptor. Used to write out deployment XML
0473: */
0474: public void setQueries(Map hashtable) {
0475: queries = hashtable;
0476: }
0477:
0478: /**
0479: * PUBLIC:
0480: * Return the query name from the set of pre-defined queries
0481: * If only one query exists with this name, it will be returned.
0482: * If there are multiple queries of this name, this method will search for a query
0483: * with no arguments and return the first one it finds.
0484: *
0485: * @see #getQuery(String, Vector)
0486: */
0487: public DatabaseQuery getQuery(String queryName) {
0488: return getQuery(queryName, null);
0489: }
0490:
0491: /**
0492: * PUBLIC:
0493: * Return the query from the set of pre-defined queries with the given name and argument types.
0494: * This allows for common queries to be pre-defined, reused and executed by name.
0495: * This method should be used if the Session has multiple queries with the same name but
0496: * different arguments.
0497: * If only one query exists, it will be returned regardless of the arguments.
0498: * If multiple queries exist, the first query that has corresponding argument types will be returned
0499: *
0500: * @see #getQuery(String)
0501: */
0502: public DatabaseQuery getQuery(String name, Vector arguments) {
0503: DatabaseQuery query = getLocalQuery(name, arguments);
0504:
0505: // CR#3711: Check if a query with the same name exists for this descriptor.
0506: // If not, recursively check descriptors of parent classes. If nothing is
0507: // found in parents, return null.
0508: if (query == null) {
0509: DatabaseQuery parentQuery = getQueryFromParent(name,
0510: arguments);
0511: if (parentQuery != null && parentQuery.isReadQuery()) {
0512: parentQuery = (DatabaseQuery) parentQuery.clone();
0513: ((ObjectLevelReadQuery) parentQuery)
0514: .setReferenceClass(getDescriptor()
0515: .getJavaClass());
0516: addQuery(name, parentQuery);
0517: }
0518: return parentQuery;
0519: }
0520: return query;
0521: }
0522:
0523: /**
0524: * INTENAL:
0525: * Return the query from the set of pre-defined queries with the given name and argument types.
0526: * This allows for common queries to be pre-defined, reused and executed by name.
0527: * Only returns those queries locally defined, not superclass's queries
0528: * If only one query exists, it will be returned regardless of the arguments.
0529: * If multiple queries exist, the first query that has corresponding argument types will be returned
0530: *
0531: * @see #getQuery(String)
0532: */
0533: public DatabaseQuery getLocalQuery(String name, Vector arguments) {
0534: Vector queries = (Vector) getQueries().get(name);
0535:
0536: if (queries == null) {
0537: return null;
0538: }
0539:
0540: // Short circuit the simple, most common case of only one query.
0541: if (queries.size() == 1) {
0542: return (DatabaseQuery) queries.firstElement();
0543: }
0544:
0545: // CR#3754; Predrag; mar 19/2002;
0546: // We allow multiple named queries with the same name but
0547: // different argument set; we can have only one query with
0548: // no arguments; Vector queries is not sorted;
0549: // When asked for the query with no parameters the
0550: // old version did return the first query - wrong:
0551: // return (DatabaseQuery) queries.firstElement();
0552: int argumentTypesSize = 0;
0553: if (arguments != null) {
0554: argumentTypesSize = arguments.size();
0555: }
0556: Vector argumentTypes = oracle.toplink.essentials.internal.helper.NonSynchronizedVector
0557: .newInstance(argumentTypesSize);
0558: for (int i = 0; i < argumentTypesSize; i++) {
0559: argumentTypes.addElement(arguments.elementAt(i).getClass());
0560: }
0561: for (Enumeration queriesEnum = queries.elements(); queriesEnum
0562: .hasMoreElements();) {
0563: DatabaseQuery query = (DatabaseQuery) queriesEnum
0564: .nextElement();
0565:
0566: // BUG#2698755
0567: // This check was backward, we default the type to Object
0568: // Was checking Object is decendent of String not other way.
0569: if (Helper.areTypesAssignable(query.getArgumentTypes(),
0570: argumentTypes)) {
0571: return query;
0572: }
0573: }
0574:
0575: return null;
0576:
0577: }
0578:
0579: /**
0580: * INTERNAL:
0581: * CR#3711: Check if the class for this descriptor has a parent class.
0582: * Then search this parent's descriptor for a query with the same name
0583: * and arguments. If nothing found, return null.
0584: *
0585: * This method should only be used recursively by getQuery().
0586: */
0587: protected DatabaseQuery getQueryFromParent(String name,
0588: Vector arguments) {
0589: ClassDescriptor descriptor = getDescriptor();
0590: if (descriptor.hasInheritance()) {
0591: InheritancePolicy inheritancePolicy = descriptor
0592: .getInheritancePolicy();
0593: ClassDescriptor parent = inheritancePolicy
0594: .getParentDescriptor();
0595:
0596: // if parent exists, check for the query
0597: if (parent != null) {
0598: return parent.getQueryManager().getQuery(name,
0599: arguments);
0600: }
0601: }
0602: return null;
0603: }
0604:
0605: /**
0606: * ADVANCED:
0607: * Return the receiver's read query.
0608: * This should be an instance of a valid subclass of ReadAllQuery.
0609: */
0610: public ReadAllQuery getReadAllQuery() {
0611: return readAllQuery;
0612: }
0613:
0614: /**
0615: * ADVANCED:
0616: * Return the receiver's read SQL string.
0617: * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
0618: * The arguments are translated from the fields of the read arguments row,
0619: * through replacing the field names marked by '#' with the values for those fields.
0620: * Note that this is only used on readAllObjects(Class), and not when an expression is provided.
0621: * <p>
0622: * Example, "select * from EMPLOYEE"
0623: */
0624: public String getReadAllSQLString() {
0625: if (getReadAllQuery() == null) {
0626: return null;
0627: }
0628:
0629: return getReadAllQuery().getSQLString();
0630: }
0631:
0632: /**
0633: * ADVANCED:
0634: * Return the receiver's read query.
0635: * This should be an instance of a valid subclass of ReadObjectQuery.
0636: * If specified this is used by the descriptor to read itself from the database.
0637: * The read arguments must be the primary key of the object only.
0638: * This gives the user the ability to define exactly how to read the object from the database,
0639: * or access data externel from the database or from some other framework.
0640: */
0641: public ReadObjectQuery getReadObjectQuery() {
0642: return readObjectQuery;
0643: }
0644:
0645: /**
0646: * ADVANCED:
0647: * Return the receiver's read SQL string.
0648: * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
0649: * The arguments are translated from the fields of the read arguments row,
0650: * through replacing the field names marked by '#' with the values for those fields.
0651: * This must accept only the primary key of the object as arguments.
0652: * <p>
0653: * Example, "select * from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID"
0654: */
0655: public String getReadObjectSQLString() {
0656: if (getReadObjectQuery() == null) {
0657: return null;
0658: }
0659:
0660: return getReadObjectQuery().getSQLString();
0661: }
0662:
0663: /**
0664: * ADVANCED:
0665: * Return the receiver's update query.
0666: * This should be an instance of a valid subclass of UpdateObjectQuery.
0667: * If specified this is used by the descriptor to insert itself into the database.
0668: * If the receiver uses optimisitic locking this must raise an error on optimisitic lock failure.
0669: * This gives the user the ability to define exactly how to update the data into the database,
0670: * or access data externel from the database or from some other framework.
0671: */
0672: public UpdateObjectQuery getUpdateQuery() {
0673: return updateQuery;
0674: }
0675:
0676: /**
0677: * ADVANCED:
0678: * Return the receiver's update SQL string.
0679: * This allows the user to override the SQL generated by TopLink, with there own SQL or procedure call.
0680: * The arguments are translated from the fields of the source row,
0681: * through replacing the field names marked by '#' with the values for those fields.
0682: * This must check the optimistic lock field and raise an error on optimistic lock failure.
0683: * <p>
0684: * Example, "update EMPLOYEE set F_NAME to #F_NAME, L_NAME to #L_NAME where EMPLOYEE_ID = #EMPLOYEE_ID".
0685: */
0686: public String getUpdateSQLString() {
0687: if (getUpdateQuery() == null) {
0688: return null;
0689: }
0690:
0691: return getUpdateQuery().getSQLString();
0692: }
0693:
0694: /**
0695: * INTERNAL:
0696: * Return if a cutsom join expression is used.
0697: */
0698: public boolean hasCustomMultipleTableJoinExpression() {
0699: return hasCustomMultipleTableJoinExpression;
0700: }
0701:
0702: /**
0703: * INTERNAL:
0704: * Flag that specifies if a delete query is available
0705: */
0706: public boolean hasDeleteQuery() {
0707: return (deleteQuery != null);
0708: }
0709:
0710: /**
0711: * INTERNAL:
0712: * Flag that specifies if a does exist query is available
0713: */
0714: public boolean hasDoesExistQuery() {
0715: return (doesExistQuery != null);
0716: }
0717:
0718: /**
0719: * INTERNAL:
0720: * Flag that specifies if a insert query is available
0721: */
0722: public boolean hasInsertQuery() {
0723: return (insertQuery != null);
0724: }
0725:
0726: /**
0727: * INTERNAL:
0728: * Flag that specifies if a read all query is available
0729: */
0730: public boolean hasReadAllQuery() {
0731: return (readAllQuery != null);
0732: }
0733:
0734: /**
0735: * INTERNAL:
0736: * Flag that specifies if a read object query is available
0737: */
0738: public boolean hasReadObjectQuery() {
0739: return (readObjectQuery != null);
0740: }
0741:
0742: /**
0743: * INTERNAL:
0744: * Flag that specifies if a update query is available
0745: */
0746: public boolean hasUpdateQuery() {
0747: return (updateQuery != null);
0748: }
0749:
0750: /**
0751: * INTERNAL:
0752: * populate the queries with the descriptor.
0753: */
0754: private void populateQueries() {
0755:
0756: /* CR2260
0757: * Descriptiron:
0758: * NullPointerException accessing null descriptor
0759: * Fix:
0760: * Initialize queries with an instantiated descriptor at this point
0761: */
0762: if (getInsertQuery() != null) {
0763: getInsertQuery().setDescriptor(descriptor);
0764: }
0765: if (getUpdateQuery() != null) {
0766: getUpdateQuery().setDescriptor(descriptor);
0767: }
0768: if (getReadObjectQuery() != null) {
0769: getReadObjectQuery().setReferenceClass(
0770: getDescriptor().getJavaClass());
0771: getReadObjectQuery().setDescriptor(descriptor);
0772: }
0773: if (getDeleteQuery() != null) {
0774: getDeleteQuery().setDescriptor(descriptor);
0775: }
0776: if (getReadAllQuery() != null) {
0777: getReadAllQuery().setReferenceClass(
0778: getDescriptor().getJavaClass());
0779: getReadAllQuery().setDescriptor(descriptor);
0780: }
0781: for (Iterator it = getAllQueries().iterator(); it.hasNext();) {
0782: ((DatabaseQuery) it.next()).setDescriptor(descriptor);
0783: }
0784: }
0785:
0786: /**
0787: * INTERNAL:
0788: * Post initialize the mappings
0789: */
0790: public void initialize(AbstractSession session) {
0791:
0792: if (getDescriptor().isAggregateDescriptor()) {
0793: return;
0794: }
0795:
0796: if (getMultipleTableJoinExpression() != null) {
0797: // Combine new multiple table expression to additional join expression
0798: setAdditionalJoinExpression(getMultipleTableJoinExpression()
0799: .and(getAdditionalJoinExpression()));
0800: }
0801:
0802: if (getDescriptor().isAggregateCollectionDescriptor()) {
0803: return;
0804: }
0805:
0806: //PERF: set read-object query to cache generated SQL.
0807: if (!hasReadObjectQuery()) {
0808: // Prepare static read object query always.
0809: ReadObjectQuery readObjectQuery = new ReadObjectQuery();
0810: readObjectQuery.setSelectionCriteria(getDescriptor()
0811: .getObjectBuilder().getPrimaryKeyExpression());
0812: setReadObjectQuery(readObjectQuery);
0813: }
0814:
0815: if (!hasInsertQuery()) {
0816: // Prepare insert query always.
0817: setInsertQuery(new InsertObjectQuery());
0818: }
0819: getInsertQuery().setModifyRow(
0820: getDescriptor().getObjectBuilder()
0821: .buildTemplateInsertRow(session));
0822:
0823: if (!hasDeleteQuery()) {
0824: // Prepare delete query always.
0825: setDeleteQuery(new DeleteObjectQuery());
0826: }
0827: getDeleteQuery().setModifyRow(new DatabaseRecord());
0828:
0829: if (hasUpdateQuery()) {
0830: // Do not prepare to update by default to allow minimal update.
0831: getUpdateQuery().setModifyRow(
0832: getDescriptor().getObjectBuilder()
0833: .buildTemplateUpdateRow(session));
0834: }
0835: }
0836:
0837: /**
0838: * INTERNAL:
0839: * Get the parent DescriptorQueryManager.
0840: * Caution must be used in using this method as it expects the descriptor
0841: * to have inheritance.
0842: * Calling this when the descriptor that does not use inheritance will cause problems, #hasInheritance() must
0843: * always first be called.
0844: */
0845: public DescriptorQueryManager getParentDescriptorQueryManager() {
0846: return getDescriptor().getInheritancePolicy()
0847: .getParentDescriptor().getQueryManager();
0848: }
0849:
0850: /**
0851: * INTERNAL:
0852: * Execute the post delete operation for the query
0853: */
0854: public void postDelete(WriteObjectQuery query) {
0855: // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
0856: Vector mappings = getDescriptor().getMappings();
0857: for (int index = 0; index < mappings.size(); index++) {
0858: ((DatabaseMapping) mappings.get(index)).postDelete(query);
0859: }
0860: }
0861:
0862: /**
0863: * INTERNAL:
0864: * Execute the post insert operation for the query
0865: */
0866: public void postInsert(WriteObjectQuery query) {
0867: // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
0868: Vector mappings = getDescriptor().getMappings();
0869: for (int index = 0; index < mappings.size(); index++) {
0870: ((DatabaseMapping) mappings.get(index)).postInsert(query);
0871: }
0872: }
0873:
0874: /**
0875: * INTERNAL:
0876: * Execute the post update operation for the query
0877: */
0878: public void postUpdate(WriteObjectQuery query) {
0879: // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
0880: Vector mappings = getDescriptor().getMappings();
0881: for (int index = 0; index < mappings.size(); index++) {
0882: ((DatabaseMapping) mappings.get(index)).postUpdate(query);
0883: }
0884: }
0885:
0886: /**
0887: * INTERNAL:
0888: * Execute the pre delete operation for the query
0889: */
0890: public void preDelete(WriteObjectQuery query) {
0891: // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
0892: Vector mappings = getDescriptor().getMappings();
0893: for (int index = 0; index < mappings.size(); index++) {
0894: ((DatabaseMapping) mappings.get(index)).preDelete(query);
0895: }
0896: }
0897:
0898: /**
0899: * INTERNAL:
0900: * Initialize the query manager.
0901: * Any custom queries must be inherited from the parent before any initialization.
0902: */
0903: public void preInitialize(AbstractSession session) {
0904: if (getDescriptor().isAggregateDescriptor()) {
0905: return;
0906: }
0907:
0908: // Must inherit parent query customization if not redefined.
0909: if (getDescriptor().isChildDescriptor()) {
0910: DescriptorQueryManager parentQueryManager = getDescriptor()
0911: .getInheritancePolicy().getParentDescriptor()
0912: .getQueryManager();
0913:
0914: if ((!hasInsertQuery())
0915: && (parentQueryManager.hasInsertQuery())) {
0916: setInsertQuery((InsertObjectQuery) parentQueryManager
0917: .getInsertQuery().clone());
0918: }
0919: if ((!hasUpdateQuery())
0920: && (parentQueryManager.hasUpdateQuery())) {
0921: setUpdateQuery((UpdateObjectQuery) parentQueryManager
0922: .getUpdateQuery().clone());
0923: }
0924: if ((!hasDeleteQuery())
0925: && (parentQueryManager.hasDeleteQuery())) {
0926: setDeleteQuery((DeleteObjectQuery) parentQueryManager
0927: .getDeleteQuery().clone());
0928: }
0929: if ((!hasReadObjectQuery())
0930: && (parentQueryManager.hasReadObjectQuery())) {
0931: setReadObjectQuery((ReadObjectQuery) parentQueryManager
0932: .getReadObjectQuery().clone());
0933: }
0934: if ((!hasReadAllQuery())
0935: && (parentQueryManager.hasReadAllQuery())) {
0936: setReadAllQuery((ReadAllQuery) parentQueryManager
0937: .getReadAllQuery().clone());
0938: }
0939: if ((!getDoesExistQuery().isUserDefined())
0940: && getDoesExistQuery()
0941: .shouldCheckCacheForDoesExist()) {
0942: setDoesExistQuery(((DoesExistQuery) parentQueryManager
0943: .getDoesExistQuery().clone()));
0944: }
0945: }
0946: }
0947:
0948: /**
0949: * INTERNAL:
0950: * Execute the pre insert operation for the query.
0951: */
0952: public void preInsert(WriteObjectQuery query) {
0953: // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
0954: Vector mappings = getDescriptor().getMappings();
0955: for (int index = 0; index < mappings.size(); index++) {
0956: ((DatabaseMapping) mappings.get(index)).preInsert(query);
0957: }
0958: }
0959:
0960: /**
0961: * INTERNAL:
0962: * Execute the pre update operation for the query
0963: */
0964: public void preUpdate(WriteObjectQuery query) {
0965: // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
0966: Vector mappings = getDescriptor().getMappings();
0967: for (int index = 0; index < mappings.size(); index++) {
0968: ((DatabaseMapping) mappings.get(index)).preUpdate(query);
0969: }
0970: }
0971:
0972: /**
0973: * PUBLIC:
0974: * Remove all queries with the given query name from the set of pre-defined queries
0975: *
0976: * @see #removeQuery(String, Vector)
0977: */
0978: public void removeQuery(String queryName) {
0979: queries.remove(queryName);
0980: }
0981:
0982: /**
0983: * PUBLIC:
0984: * Remove the specific query with the given queryName and argumentTypes.
0985: *
0986: * @see #removeQuery(String)
0987: */
0988: public void removeQuery(String queryName, Vector argumentTypes) {
0989: Vector queries = (Vector) getQueries().get(queryName);
0990: if (queries == null) {
0991: return;
0992: } else {
0993: DatabaseQuery query = null;
0994: for (Enumeration enumtr = queries.elements(); enumtr
0995: .hasMoreElements();) {
0996: query = (DatabaseQuery) enumtr.nextElement();
0997: if (Helper.areTypesAssignable(argumentTypes, query
0998: .getArgumentTypes())) {
0999: break;
1000: }
1001: }
1002: if (query != null) {
1003: queries.remove(query);
1004: }
1005: }
1006: }
1007:
1008: /**
1009: * ADVANCED:
1010: * Set the additional join expression. Used in conjuction with
1011: * multiple tables and inheritance relationships.
1012: * This can also be used if a sub-expression is always required to be
1013: * appended to all queries. Such as tables that are shared based on a type field
1014: * without inheritance.
1015: */
1016: public void setAdditionalJoinExpression(
1017: Expression additionalJoinExpression) {
1018: this .additionalJoinExpression = additionalJoinExpression;
1019: }
1020:
1021: /**
1022: * ADVANCED:
1023: * Set the receiver's delete query.
1024: * This should be an instance of a valid subclas of DeleteObjectQuery.
1025: * If specified this is used by the descriptor to delete itself and its private parts from the database.
1026: * This gives the user the ability to define exactly how to delete the data from the database,
1027: * or access data external from the database or from some other framework.
1028: */
1029: public void setDeleteQuery(DeleteObjectQuery query) {
1030: this .deleteQuery = query;
1031: if (query == null) {
1032: return;
1033: }
1034: this .deleteQuery.setIsUserDefined(true);
1035: this .deleteQuery.setDescriptor(getDescriptor());
1036:
1037: }
1038:
1039: /**
1040: * ADVANCED:
1041: * Set the receiver's delete SQL string.
1042: * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
1043: * The arguments are translated from the fields of the source row,
1044: * through replacing the field names marked by '#' with the values for those fields.
1045: * <p>
1046: * Example, "delete from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID".
1047: */
1048: public void setDeleteSQLString(String sqlString) {
1049: if (sqlString == null) {
1050: return;
1051: }
1052:
1053: DeleteObjectQuery query = new DeleteObjectQuery();
1054: query.setSQLString(sqlString);
1055: setDeleteQuery(query);
1056: }
1057:
1058: /**
1059: * ADVANCED:
1060: * Set the receiver's delete call.
1061: * This allows the user to override the delete operation.
1062: */
1063: public void setDeleteCall(Call call) {
1064: if (call == null) {
1065: return;
1066: }
1067: DeleteObjectQuery query = new DeleteObjectQuery();
1068: query.setCall(call);
1069: setDeleteQuery(query);
1070: }
1071:
1072: /**
1073: * INTERNAL:
1074: * Set the descriptor.
1075: */
1076: public void setDescriptor(ClassDescriptor descriptor) {
1077: this .descriptor = descriptor;
1078: //Gross alert: This is for the case when we are reading from XML, and
1079: //we have to compensate for no descriptor available at read time. - JL
1080: populateQueries();
1081:
1082: }
1083:
1084: /**
1085: * ADVANCED:
1086: * Set the receiver's does exist query.
1087: * This should be an instance of a valid subclas of DoesExistQuery.
1088: * If specified this is used by the descriptor to query existence of an object in the database.
1089: * This gives the user the ability to define exactly how to query existence from the database,
1090: * or access data external from the database or from some other framework.
1091: */
1092: public void setDoesExistQuery(DoesExistQuery query) {
1093: this .doesExistQuery = query;
1094: if (query == null) {
1095: return;
1096: }
1097: this .doesExistQuery.setIsUserDefined(true);
1098: this .doesExistQuery.setDescriptor(getDescriptor());
1099: }
1100:
1101: /**
1102: * ADVANCED:
1103: * Set the receiver's does exist SQL string.
1104: * This allows the user to override the SQL generated by TopLink, with there own SQL or procedure call.
1105: * The arguments are translated from the fields of the source row, through replacing the field names marked by '#'
1106: * with the values for those fields.
1107: * This must return null if the object does not exist, otherwise return a database row.
1108: * <p>
1109: * Example, "select EMPLOYEE_ID from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID".
1110: */
1111: public void setDoesExistSQLString(String sqlString) {
1112: if (sqlString == null) {
1113: return;
1114: }
1115: getDoesExistQuery().setSQLString(sqlString);
1116: getDoesExistQuery().checkDatabaseForDoesExist();
1117: }
1118:
1119: /**
1120: * ADVANCED:
1121: * Set the receiver's does exist call.
1122: * This allows the user to override the does exist operation.
1123: */
1124: public void setDoesExistCall(Call call) {
1125: if (call == null) {
1126: return;
1127: }
1128: getDoesExistQuery().setCall(call);
1129: }
1130:
1131: /**
1132: * INTERNAL:
1133: * This method is explicitly used by the Builder only.
1134: */
1135: public void setExistenceCheck(String token)
1136: throws DescriptorException {
1137: if (token.equals("Check cache")) {
1138: checkCacheForDoesExist();
1139: } else if (token.equals("Check database")) {
1140: checkDatabaseForDoesExist();
1141: } else if (token.equals("Assume existence")) {
1142: assumeExistenceForDoesExist();
1143: } else if (token.equals("Assume non-existence")) {
1144: assumeNonExistenceForDoesExist();
1145: } else {
1146: throw DescriptorException
1147: .setExistenceCheckingNotUnderstood(token,
1148: getDescriptor());
1149: }
1150: }
1151:
1152: /**
1153: * INTENAL:
1154: * Set if a cutsom join expression is used.
1155: */
1156: protected void setHasCustomMultipleTableJoinExpression(
1157: boolean hasCustomMultipleTableJoinExpression) {
1158: this .hasCustomMultipleTableJoinExpression = hasCustomMultipleTableJoinExpression;
1159: }
1160:
1161: /**
1162: * ADVANCED:
1163: * Set the receiver's insert query.
1164: * This should be an instance of a valid subclass of InsertObjectQuery.
1165: * If specified this is used by the descriptor to insert itself into the database.
1166: * This gives the user the ability to define exactly how to insert the data into the database,
1167: * or access data external from the database or from some other framework.
1168: */
1169: public void setInsertQuery(InsertObjectQuery insertQuery) {
1170: this .insertQuery = insertQuery;
1171: if (insertQuery == null) {
1172: return;
1173: }
1174: this .insertQuery.setIsUserDefined(true);
1175: this .insertQuery.setDescriptor(getDescriptor());
1176: }
1177:
1178: /**
1179: * ADVANCED:
1180: * Set the receiver's insert call.
1181: * This allows the user to override the insert operation.
1182: */
1183: public void setInsertCall(Call call) {
1184: if (call == null) {
1185: return;
1186: }
1187: InsertObjectQuery query = new InsertObjectQuery();
1188: query.setCall(call);
1189: setInsertQuery(query);
1190: }
1191:
1192: /**
1193: * ADVANCED:
1194: * Set the receiver's insert SQL string.
1195: * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
1196: * The arguments are translated from the fields of the source row,
1197: * through replacing the field names marked by '#' with the values for those fields.
1198: * <p>
1199: * Example, "insert into EMPLOYEE (F_NAME, L_NAME) values (#F_NAME, #L_NAME)".
1200: */
1201: public void setInsertSQLString(String sqlString) {
1202: if (sqlString == null) {
1203: return;
1204: }
1205:
1206: InsertObjectQuery query = new InsertObjectQuery();
1207: query.setSQLString(sqlString);
1208: setInsertQuery(query);
1209: }
1210:
1211: /**
1212: * ADVANCED:
1213: * Return the receiver's insert call.
1214: * This allows the user to override the insert operation.
1215: */
1216: public Call getInsertCall() {
1217: if (getInsertQuery() == null) {
1218: return null;
1219: }
1220: return getInsertQuery().getDatasourceCall();
1221: }
1222:
1223: /**
1224: * ADVANCED:
1225: * Return the receiver's update call.
1226: * This allows the user to override the update operation.
1227: */
1228: public Call getUpdateCall() {
1229: if (getUpdateQuery() == null) {
1230: return null;
1231: }
1232: return getUpdateQuery().getDatasourceCall();
1233: }
1234:
1235: /**
1236: * ADVANCED:
1237: * Return the receiver's delete call.
1238: * This allows the user to override the delete operation.
1239: */
1240: public Call getDeleteCall() {
1241: if (getDeleteQuery() == null) {
1242: return null;
1243: }
1244: return getDeleteQuery().getDatasourceCall();
1245: }
1246:
1247: /**
1248: * ADVANCED:
1249: * Return the receiver's read-object call.
1250: * This allows the user to override the read-object operation.
1251: */
1252: public Call getReadObjectCall() {
1253: if (getReadObjectQuery() == null) {
1254: return null;
1255: }
1256: return getReadObjectQuery().getDatasourceCall();
1257: }
1258:
1259: /**
1260: * ADVANCED:
1261: * Return the receiver's read-all call.
1262: * This allows the user to override the read-all operation.
1263: */
1264: public Call getReadAllCall() {
1265: if (getReadAllQuery() == null) {
1266: return null;
1267: }
1268: return getReadAllQuery().getDatasourceCall();
1269: }
1270:
1271: /**
1272: * ADVANCED:
1273: * Return the receiver's does-exist call.
1274: * This allows the user to override the does-exist operation.
1275: */
1276: public Call getDoesExistCall() {
1277: if (getDoesExistQuery() == null) {
1278: return null;
1279: }
1280: return getDoesExistQuery().getDatasourceCall();
1281: }
1282:
1283: /**
1284: * INTERNAL:
1285: * Used in case descriptor has additional tables:
1286: * each additional table mapped to an expression joining it.
1287: */
1288: public Map getTablesJoinExpressions() {
1289: if (tablesJoinExpressions == null) {
1290: tablesJoinExpressions = new HashMap();
1291: }
1292: return tablesJoinExpressions;
1293: }
1294:
1295: /**
1296: * INTERNAL:
1297: * Used to set the multiple table join expression that was generated by TopLink as opposed
1298: * to a custom one supplied by the user.
1299: * @see #setMultipleTableJoinExpression(Expression)
1300: */
1301: public void setInternalMultipleTableJoinExpression(
1302: Expression multipleTableJoinExpression) {
1303: this .multipleTableJoinExpression = multipleTableJoinExpression;
1304: }
1305:
1306: /**
1307: * ADVANCED:
1308: * This is normally generated for descriptors that have multiple tables.
1309: * However, if the additional table does not reference the primary table's primary key,
1310: * this expression may be set directly.
1311: */
1312: public void setMultipleTableJoinExpression(
1313: Expression multipleTableJoinExpression) {
1314: this .multipleTableJoinExpression = multipleTableJoinExpression;
1315: setHasCustomMultipleTableJoinExpression(true);
1316: }
1317:
1318: /**
1319: * ADVANCED:
1320: * Set the receiver's read all query.
1321: * This should be an instance of a valid subclass of ReadAllQuery.
1322: * If specified this is used by the descriptor to read all instances of its class from the database.
1323: * This gives the user the ability to define exactly how to read all objects from the database,
1324: * or access data external from the database or from some other framework.
1325: * Note that this is only used on readAllObjects(Class), and not when an expression is provided.
1326: */
1327: public void setReadAllQuery(ReadAllQuery query) {
1328: this .readAllQuery = query;
1329: if (query == null) {
1330: return;
1331: }
1332:
1333: this .readAllQuery.setIsUserDefined(true);
1334:
1335: /* CR2260 - Steven Vo
1336: * Description:
1337: * NullPointerException accessing null descriptor
1338: * Fix:
1339: * Setting query's descriptor and reference class when descriptor is not null.
1340: * Otherwise, wait until the descriptor is set.See populateQueries() that is
1341: * called by setDescriptor()
1342: */
1343: if (this .getDescriptor() != null) {
1344: this .readAllQuery.setDescriptor(getDescriptor());
1345: this .readAllQuery.setReferenceClassName(getDescriptor()
1346: .getJavaClassName());
1347: try {
1348: readAllQuery.setReferenceClass(getDescriptor()
1349: .getJavaClass());
1350: } catch (ConversionException exception) {
1351: }
1352: }
1353: }
1354:
1355: /**
1356: * ADVANCED:
1357: * Set the receiver's read SQL string.
1358: * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
1359: * The arguments are translated from the fields of the read arguments row,
1360: * through replacing the field names marked by '#' with the values for those fields.
1361: * Note that this is only used on readAllObjects(Class), and not when an expression is provided.
1362: * <p>
1363: * Example, "select * from EMPLOYEE"
1364: */
1365: public void setReadAllSQLString(String sqlString) {
1366: if (sqlString == null) {
1367: return;
1368: }
1369:
1370: ReadAllQuery query = new ReadAllQuery();
1371: query.setSQLString(sqlString);
1372: setReadAllQuery(query);
1373: }
1374:
1375: /**
1376: * ADVANCED:
1377: * Set the receiver's read all call.
1378: * This allows the user to override the read all operation.
1379: * Note that this is only used on readAllObjects(Class), and not when an expression is provided.
1380: */
1381: public void setReadAllCall(Call call) {
1382: if (call == null) {
1383: return;
1384: }
1385: ReadAllQuery query = new ReadAllQuery();
1386: query.setCall(call);
1387: setReadAllQuery(query);
1388: }
1389:
1390: /**
1391: * ADVANCED:
1392: * Set the receiver's read query.
1393: * This should be an instance of a valid subclass of ReadObjectQuery>
1394: * If specified this is used by the descriptor to read itself from the database.
1395: * The read arguments must be the primary key of the object only.
1396: * This gives the user the ability to define exactly how to read the object from the database,
1397: * or access data external from the database or from some other framework.
1398: */
1399: public void setReadObjectQuery(ReadObjectQuery query) {
1400: this .readObjectQuery = query;
1401: if (query == null) {
1402: return;
1403: }
1404: this .readObjectQuery.setIsUserDefined(true);
1405:
1406: /* CR2260 - Steven Vo
1407: * Description:
1408: * NullPointerException accessing null descriptor
1409: * Fix:
1410: * Setting query's descriptor and reference class when descriptor is not null.
1411: * Otherwise, wait until the descriptor is set.See populateQueries() that is
1412: * called by setDescriptor()
1413: */
1414: if (this .getDescriptor() != null) {
1415: this .readObjectQuery.setDescriptor(getDescriptor());
1416: this .readObjectQuery.setReferenceClassName(getDescriptor()
1417: .getJavaClassName());
1418: try {
1419: readObjectQuery.setReferenceClass(getDescriptor()
1420: .getJavaClass());
1421: } catch (ConversionException exception) {
1422: }
1423: }
1424: }
1425:
1426: /**
1427: * ADVANCED:
1428: * Set the receiver's read SQL string.
1429: * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
1430: * The arguments are translated from the fields of the read arguments row,
1431: * through replacing the field names marked by '#' with the values for those fields.
1432: * This must accept only the primary key of the object as arguments.
1433: * <p>
1434: * Example, "select * from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID"
1435: */
1436: public void setReadObjectSQLString(String sqlString) {
1437: if (sqlString == null) {
1438: return;
1439: }
1440:
1441: ReadObjectQuery query = new ReadObjectQuery();
1442: query.setSQLString(sqlString);
1443: setReadObjectQuery(query);
1444: }
1445:
1446: /**
1447: * ADVANCED:
1448: * Set the receiver's read object call.
1449: * This allows the user to override the read object operation.
1450: * This must accept only the primary key of the object as arguments.
1451: */
1452: public void setReadObjectCall(Call call) {
1453: if (call == null) {
1454: return;
1455: }
1456: ReadObjectQuery query = new ReadObjectQuery();
1457: query.setCall(call);
1458: setReadObjectQuery(query);
1459: }
1460:
1461: /**
1462: * ADVANCED:
1463: * Set the receiver's update query.
1464: * This should be an instance of a valid subclass of UpdateObjectQuery.
1465: * If specified this is used by the descriptor to update itself in the database.
1466: * If the receiver uses optimisitic locking this must raise an error on optimisitic lock failure.
1467: * This gives the user the ability to define exactly how to update the data into the database,
1468: * or access data external from the database or from some other framework.
1469: */
1470: public void setUpdateQuery(UpdateObjectQuery updateQuery) {
1471: this .updateQuery = updateQuery;
1472: if (updateQuery == null) {
1473: return;
1474: }
1475: this .updateQuery.setIsUserDefined(true);
1476: this .updateQuery.setDescriptor(getDescriptor());
1477: }
1478:
1479: /**
1480: * ADVANCED:
1481: * Set the receiver's update SQL string.
1482: * This allows the user to override the SQL generated by TopLink, with there own SQL or procedure call.
1483: * The arguments are translated from the fields of the source row,
1484: * through replacing the field names marked by '#' with the values for those fields.
1485: * This must check the optimistic lock field and raise an error on optimistic lock failure.
1486: * <p>
1487: * Example, "update EMPLOYEE set F_NAME to #F_NAME, L_NAME to #L_NAME where EMPLOYEE_ID = #EMPLOYEE_ID".
1488: */
1489: public void setUpdateSQLString(String sqlString) {
1490: if (sqlString == null) {
1491: return;
1492: }
1493:
1494: UpdateObjectQuery query = new UpdateObjectQuery();
1495: query.setSQLString(sqlString);
1496: setUpdateQuery(query);
1497: }
1498:
1499: /**
1500: * ADVANCED:
1501: * Set the receiver's update call.
1502: * This allows the user to override the update operation.
1503: */
1504: public void setUpdateCall(Call call) {
1505: if (call == null) {
1506: return;
1507: }
1508: UpdateObjectQuery query = new UpdateObjectQuery();
1509: query.setCall(call);
1510: setUpdateQuery(query);
1511: }
1512: }
|