0001: /*
0002: * Copyright 2004 Clinton Begin
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016: package com.ibatis.sqlmap.engine.impl;
0017:
0018: import com.ibatis.common.beans.Probe;
0019: import com.ibatis.common.beans.ProbeFactory;
0020: import com.ibatis.common.jdbc.exception.NestedSQLException;
0021: import com.ibatis.common.util.PaginatedList;
0022: import com.ibatis.common.util.ThrottledPool;
0023: import com.ibatis.sqlmap.client.SqlMapException;
0024: import com.ibatis.sqlmap.client.event.RowHandler;
0025: import com.ibatis.sqlmap.engine.cache.CacheKey;
0026: import com.ibatis.sqlmap.engine.cache.CacheModel;
0027: import com.ibatis.sqlmap.engine.exchange.DataExchangeFactory;
0028: import com.ibatis.sqlmap.engine.execution.BatchException;
0029: import com.ibatis.sqlmap.engine.execution.SqlExecutor;
0030: import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
0031: import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
0032: import com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactory;
0033: import com.ibatis.sqlmap.engine.mapping.statement.InsertStatement;
0034: import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
0035: import com.ibatis.sqlmap.engine.mapping.statement.PaginatedDataList;
0036: import com.ibatis.sqlmap.engine.mapping.statement.SelectKeyStatement;
0037: import com.ibatis.sqlmap.engine.scope.RequestScope;
0038: import com.ibatis.sqlmap.engine.scope.SessionScope;
0039: import com.ibatis.sqlmap.engine.transaction.Transaction;
0040: import com.ibatis.sqlmap.engine.transaction.TransactionException;
0041: import com.ibatis.sqlmap.engine.transaction.TransactionManager;
0042: import com.ibatis.sqlmap.engine.transaction.TransactionState;
0043: import com.ibatis.sqlmap.engine.transaction.user.UserProvidedTransaction;
0044: import com.ibatis.sqlmap.engine.type.TypeHandlerFactory;
0045:
0046: import javax.sql.DataSource;
0047: import java.sql.Connection;
0048: import java.sql.SQLException;
0049: import java.util.HashMap;
0050: import java.util.Iterator;
0051: import java.util.List;
0052: import java.util.Map;
0053:
0054: /**
0055: * The workhorse that really runs the SQL
0056: */
0057: public class SqlMapExecutorDelegate {
0058:
0059: private static final Probe PROBE = ProbeFactory.getProbe();
0060:
0061: /**
0062: * The default maximum number of requests
0063: */
0064: public static final int DEFAULT_MAX_REQUESTS = 512;
0065: /**
0066: * The default maximum number of sessions
0067: */
0068: public static final int DEFAULT_MAX_SESSIONS = 128;
0069: /**
0070: * The default maximum number of transactions
0071: */
0072: public static final int DEFAULT_MAX_TRANSACTIONS = 32;
0073:
0074: private boolean lazyLoadingEnabled;
0075: private boolean cacheModelsEnabled;
0076: private boolean enhancementEnabled;
0077:
0078: private int maxRequests = DEFAULT_MAX_REQUESTS;
0079: private int maxSessions = DEFAULT_MAX_SESSIONS;
0080: private int maxTransactions = DEFAULT_MAX_TRANSACTIONS;
0081:
0082: private TransactionManager txManager;
0083:
0084: private HashMap mappedStatements;
0085: private HashMap cacheModels;
0086: private HashMap resultMaps;
0087: private HashMap parameterMaps;
0088:
0089: private ThrottledPool requestPool;
0090: private ThrottledPool sessionPool;
0091:
0092: protected SqlExecutor sqlExecutor;
0093: private TypeHandlerFactory typeHandlerFactory;
0094: private DataExchangeFactory dataExchangeFactory;
0095:
0096: private ResultObjectFactory resultObjectFactory;
0097: private boolean statementCacheEnabled;
0098:
0099: /**
0100: * Default constructor
0101: */
0102: public SqlMapExecutorDelegate() {
0103: mappedStatements = new HashMap();
0104: cacheModels = new HashMap();
0105: resultMaps = new HashMap();
0106: parameterMaps = new HashMap();
0107:
0108: requestPool = new ThrottledPool(RequestScope.class,
0109: DEFAULT_MAX_REQUESTS);
0110: sessionPool = new ThrottledPool(SessionScope.class,
0111: DEFAULT_MAX_SESSIONS);
0112:
0113: sqlExecutor = new SqlExecutor();
0114: typeHandlerFactory = new TypeHandlerFactory();
0115: dataExchangeFactory = new DataExchangeFactory(
0116: typeHandlerFactory);
0117: }
0118:
0119: /**
0120: * Getter for the DataExchangeFactory
0121: *
0122: * @return - the DataExchangeFactory
0123: */
0124: public DataExchangeFactory getDataExchangeFactory() {
0125: return dataExchangeFactory;
0126: }
0127:
0128: /**
0129: * Getter for the TypeHandlerFactory
0130: *
0131: * @return - the TypeHandlerFactory
0132: */
0133: public TypeHandlerFactory getTypeHandlerFactory() {
0134: return typeHandlerFactory;
0135: }
0136:
0137: /**
0138: * Getter for the status of lazy loading
0139: *
0140: * @return - the status
0141: */
0142: public boolean isLazyLoadingEnabled() {
0143: return lazyLoadingEnabled;
0144: }
0145:
0146: /**
0147: * Turn on or off lazy loading
0148: *
0149: * @param lazyLoadingEnabled - the new state of caching
0150: */
0151: public void setLazyLoadingEnabled(boolean lazyLoadingEnabled) {
0152: this .lazyLoadingEnabled = lazyLoadingEnabled;
0153: }
0154:
0155: /**
0156: * Getter for the status of caching
0157: *
0158: * @return - the status
0159: */
0160: public boolean isCacheModelsEnabled() {
0161: return cacheModelsEnabled;
0162: }
0163:
0164: /**
0165: * Turn on or off caching
0166: *
0167: * @param cacheModelsEnabled - the new state of caching
0168: */
0169: public void setCacheModelsEnabled(boolean cacheModelsEnabled) {
0170: this .cacheModelsEnabled = cacheModelsEnabled;
0171: }
0172:
0173: /**
0174: * Getter for the status of CGLib enhancements
0175: *
0176: * @return - the status
0177: */
0178: public boolean isEnhancementEnabled() {
0179: return enhancementEnabled;
0180: }
0181:
0182: /**
0183: * Turn on or off CGLib enhancements
0184: *
0185: * @param enhancementEnabled - the new state
0186: */
0187: public void setEnhancementEnabled(boolean enhancementEnabled) {
0188: this .enhancementEnabled = enhancementEnabled;
0189: }
0190:
0191: /**
0192: * Getter for the maximum number of requests
0193: *
0194: * @return - the maximum number of requests
0195: */
0196: public int getMaxRequests() {
0197: return maxRequests;
0198: }
0199:
0200: /**
0201: * Setter for the maximum number of requests
0202: *
0203: * @param maxRequests - the maximum number of requests
0204: */
0205: public void setMaxRequests(int maxRequests) {
0206: this .maxRequests = maxRequests;
0207: requestPool = new ThrottledPool(RequestScope.class, maxRequests);
0208: }
0209:
0210: /**
0211: * Getter for the maximum number of sessions
0212: *
0213: * @return - the maximum number of sessions
0214: */
0215: public int getMaxSessions() {
0216: return maxSessions;
0217: }
0218:
0219: /**
0220: * Setter for the maximum number of sessions
0221: *
0222: * @param maxSessions - the maximum number of sessions
0223: */
0224: public void setMaxSessions(int maxSessions) {
0225: this .maxSessions = maxSessions;
0226: this .sessionPool = new ThrottledPool(SessionScope.class,
0227: maxSessions);
0228: }
0229:
0230: /**
0231: * Getter for the the maximum number of transactions
0232: *
0233: * @return - the maximum number of transactions
0234: */
0235: public int getMaxTransactions() {
0236: return maxTransactions;
0237: }
0238:
0239: /**
0240: * Setter for the maximum number of transactions
0241: *
0242: * @param maxTransactions - the maximum number of transactions
0243: */
0244: public void setMaxTransactions(int maxTransactions) {
0245: this .maxTransactions = maxTransactions;
0246: }
0247:
0248: /**
0249: * Getter for the transaction manager
0250: *
0251: * @return - the transaction manager
0252: */
0253: public TransactionManager getTxManager() {
0254: return txManager;
0255: }
0256:
0257: /**
0258: * Setter for the transaction manager
0259: *
0260: * @param txManager - the transaction manager
0261: */
0262: public void setTxManager(TransactionManager txManager) {
0263: this .txManager = txManager;
0264: }
0265:
0266: /**
0267: * Add a mapped statement
0268: *
0269: * @param ms - the mapped statement to add
0270: */
0271: public void addMappedStatement(MappedStatement ms) {
0272: if (mappedStatements.containsKey(ms.getId())) {
0273: throw new SqlMapException(
0274: "There is already a statement named " + ms.getId()
0275: + " in this SqlMap.");
0276: }
0277: ms.setBaseCacheKey(hashCode());
0278: mappedStatements.put(ms.getId(), ms);
0279: }
0280:
0281: /**
0282: * Get an iterator of the mapped statements
0283: *
0284: * @return - the iterator
0285: */
0286: public Iterator getMappedStatementNames() {
0287: return mappedStatements.keySet().iterator();
0288: }
0289:
0290: /**
0291: * Get a mappedstatement by its ID
0292: *
0293: * @param id - the statement ID
0294: * @return - the mapped statement
0295: */
0296: public MappedStatement getMappedStatement(String id) {
0297: MappedStatement ms = (MappedStatement) mappedStatements.get(id);
0298: if (ms == null) {
0299: throw new SqlMapException("There is no statement named "
0300: + id + " in this SqlMap.");
0301: }
0302: return ms;
0303: }
0304:
0305: /**
0306: * Add a cache model
0307: *
0308: * @param model - the model to add
0309: */
0310: public void addCacheModel(CacheModel model) {
0311: cacheModels.put(model.getId(), model);
0312: }
0313:
0314: /**
0315: * Get an iterator of the cache models
0316: *
0317: * @return - the cache models
0318: */
0319: public Iterator getCacheModelNames() {
0320: return cacheModels.keySet().iterator();
0321: }
0322:
0323: /**
0324: * Get a cache model by ID
0325: *
0326: * @param id - the ID
0327: * @return - the cache model
0328: */
0329: public CacheModel getCacheModel(String id) {
0330: CacheModel model = (CacheModel) cacheModels.get(id);
0331: if (model == null) {
0332: throw new SqlMapException("There is no cache model named "
0333: + id + " in this SqlMap.");
0334: }
0335: return model;
0336: }
0337:
0338: /**
0339: * Add a result map
0340: *
0341: * @param map - the result map to add
0342: */
0343: public void addResultMap(ResultMap map) {
0344: resultMaps.put(map.getId(), map);
0345: }
0346:
0347: /**
0348: * Get an iterator of the result maps
0349: *
0350: * @return - the result maps
0351: */
0352: public Iterator getResultMapNames() {
0353: return resultMaps.keySet().iterator();
0354: }
0355:
0356: /**
0357: * Get a result map by ID
0358: *
0359: * @param id - the ID
0360: * @return - the result map
0361: */
0362: public ResultMap getResultMap(String id) {
0363: ResultMap map = (ResultMap) resultMaps.get(id);
0364: if (map == null) {
0365: throw new SqlMapException("There is no result map named "
0366: + id + " in this SqlMap.");
0367: }
0368: return map;
0369: }
0370:
0371: /**
0372: * Add a parameter map
0373: *
0374: * @param map - the map to add
0375: */
0376: public void addParameterMap(ParameterMap map) {
0377: parameterMaps.put(map.getId(), map);
0378: }
0379:
0380: /**
0381: * Get an iterator of all of the parameter maps
0382: *
0383: * @return - the parameter maps
0384: */
0385: public Iterator getParameterMapNames() {
0386: return parameterMaps.keySet().iterator();
0387: }
0388:
0389: /**
0390: * Get a parameter map by ID
0391: *
0392: * @param id - the ID
0393: * @return - the parameter map
0394: */
0395: public ParameterMap getParameterMap(String id) {
0396: ParameterMap map = (ParameterMap) parameterMaps.get(id);
0397: if (map == null) {
0398: throw new SqlMapException(
0399: "There is no parameter map named " + id
0400: + " in this SqlMap.");
0401: }
0402: return map;
0403: }
0404:
0405: /**
0406: * Flush all of the data caches
0407: */
0408: public void flushDataCache() {
0409: Iterator models = cacheModels.values().iterator();
0410: while (models.hasNext()) {
0411: ((CacheModel) models.next()).flush();
0412: }
0413: }
0414:
0415: /**
0416: * Flush a single cache by ID
0417: *
0418: * @param id - the ID
0419: */
0420: public void flushDataCache(String id) {
0421: CacheModel model = getCacheModel(id);
0422: if (model != null) {
0423: model.flush();
0424: }
0425: }
0426:
0427: //-- Basic Methods
0428: /**
0429: * Call an insert statement by ID
0430: *
0431: * @param session - the session
0432: * @param id - the statement ID
0433: * @param param - the parameter object
0434: * @return - the generated key (or null)
0435: * @throws SQLException - if the insert fails
0436: */
0437: public Object insert(SessionScope session, String id, Object param)
0438: throws SQLException {
0439: Object generatedKey = null;
0440:
0441: MappedStatement ms = getMappedStatement(id);
0442: Transaction trans = getTransaction(session);
0443: boolean autoStart = trans == null;
0444:
0445: try {
0446: trans = autoStartTransaction(session, autoStart, trans);
0447:
0448: SelectKeyStatement selectKeyStatement = null;
0449: if (ms instanceof InsertStatement) {
0450: selectKeyStatement = ((InsertStatement) ms)
0451: .getSelectKeyStatement();
0452: }
0453:
0454: if (selectKeyStatement != null
0455: && !selectKeyStatement.isAfter()) {
0456: generatedKey = executeSelectKey(session, trans, ms,
0457: param);
0458: }
0459:
0460: RequestScope request = popRequest(session, ms);
0461: try {
0462: ms.executeUpdate(request, trans, param);
0463: } finally {
0464: pushRequest(request);
0465: }
0466:
0467: if (selectKeyStatement != null
0468: && selectKeyStatement.isAfter()) {
0469: generatedKey = executeSelectKey(session, trans, ms,
0470: param);
0471: }
0472:
0473: autoCommitTransaction(session, autoStart);
0474: } finally {
0475: autoEndTransaction(session, autoStart);
0476: }
0477:
0478: return generatedKey;
0479: }
0480:
0481: private Object executeSelectKey(SessionScope session,
0482: Transaction trans, MappedStatement ms, Object param)
0483: throws SQLException {
0484: Object generatedKey = null;
0485: RequestScope request;
0486: InsertStatement insert = (InsertStatement) ms;
0487: SelectKeyStatement selectKeyStatement = insert
0488: .getSelectKeyStatement();
0489: if (selectKeyStatement != null) {
0490: request = popRequest(session, selectKeyStatement);
0491: try {
0492: generatedKey = selectKeyStatement
0493: .executeQueryForObject(request, trans, param,
0494: null);
0495: String keyProp = selectKeyStatement.getKeyProperty();
0496: if (keyProp != null) {
0497: PROBE.setObject(param, keyProp, generatedKey);
0498: }
0499: } finally {
0500: pushRequest(request);
0501: }
0502: }
0503: return generatedKey;
0504: }
0505:
0506: /**
0507: * Execute an update statement
0508: *
0509: * @param session - the session scope
0510: * @param id - the statement ID
0511: * @param param - the parameter object
0512: * @return - the number of rows updated
0513: * @throws SQLException - if the update fails
0514: */
0515: public int update(SessionScope session, String id, Object param)
0516: throws SQLException {
0517: int rows = 0;
0518:
0519: MappedStatement ms = getMappedStatement(id);
0520: Transaction trans = getTransaction(session);
0521: boolean autoStart = trans == null;
0522:
0523: try {
0524: trans = autoStartTransaction(session, autoStart, trans);
0525:
0526: RequestScope request = popRequest(session, ms);
0527: try {
0528: rows = ms.executeUpdate(request, trans, param);
0529: } finally {
0530: pushRequest(request);
0531: }
0532:
0533: autoCommitTransaction(session, autoStart);
0534: } finally {
0535: autoEndTransaction(session, autoStart);
0536: }
0537:
0538: return rows;
0539: }
0540:
0541: /**
0542: * Execute a delete statement
0543: *
0544: * @param session - the session scope
0545: * @param id - the statement ID
0546: * @param param - the parameter object
0547: * @return - the number of rows deleted
0548: * @throws SQLException - if the delete fails
0549: */
0550: public int delete(SessionScope session, String id, Object param)
0551: throws SQLException {
0552: return update(session, id, param);
0553: }
0554:
0555: /**
0556: * Execute a select for a single object
0557: *
0558: * @param session - the session scope
0559: * @param id - the statement ID
0560: * @param paramObject - the parameter object
0561: * @return - the result of the query
0562: * @throws SQLException - if the query fails
0563: */
0564: public Object queryForObject(SessionScope session, String id,
0565: Object paramObject) throws SQLException {
0566: return queryForObject(session, id, paramObject, null);
0567: }
0568:
0569: /**
0570: * Execute a select for a single object
0571: *
0572: * @param session - the session scope
0573: * @param id - the statement ID
0574: * @param paramObject - the parameter object
0575: * @param resultObject - the result object (if not supplied or null, a new object will be created)
0576: * @return - the result of the query
0577: * @throws SQLException - if the query fails
0578: */
0579: public Object queryForObject(SessionScope session, String id,
0580: Object paramObject, Object resultObject)
0581: throws SQLException {
0582: Object object = null;
0583:
0584: MappedStatement ms = getMappedStatement(id);
0585: Transaction trans = getTransaction(session);
0586: boolean autoStart = trans == null;
0587:
0588: try {
0589: trans = autoStartTransaction(session, autoStart, trans);
0590:
0591: RequestScope request = popRequest(session, ms);
0592: try {
0593: object = ms.executeQueryForObject(request, trans,
0594: paramObject, resultObject);
0595: } finally {
0596: pushRequest(request);
0597: }
0598:
0599: autoCommitTransaction(session, autoStart);
0600: } finally {
0601: autoEndTransaction(session, autoStart);
0602: }
0603:
0604: return object;
0605: }
0606:
0607: /**
0608: * Execute a query for a list
0609: *
0610: * @param session - the session scope
0611: * @param id - the statement ID
0612: * @param paramObject - the parameter object
0613: * @return - the data list
0614: * @throws SQLException - if the query fails
0615: */
0616: public List queryForList(SessionScope session, String id,
0617: Object paramObject) throws SQLException {
0618: return queryForList(session, id, paramObject,
0619: SqlExecutor.NO_SKIPPED_RESULTS,
0620: SqlExecutor.NO_MAXIMUM_RESULTS);
0621: }
0622:
0623: /**
0624: * Execute a query for a list
0625: *
0626: * @param session - the session scope
0627: * @param id - the statement ID
0628: * @param paramObject - the parameter object
0629: * @param skip - the number of rows to skip
0630: * @param max - the maximum number of rows to return
0631: * @return - the data list
0632: * @throws SQLException - if the query fails
0633: */
0634: public List queryForList(SessionScope session, String id,
0635: Object paramObject, int skip, int max) throws SQLException {
0636: List list = null;
0637:
0638: MappedStatement ms = getMappedStatement(id);
0639: Transaction trans = getTransaction(session);
0640: boolean autoStart = trans == null;
0641:
0642: try {
0643: trans = autoStartTransaction(session, autoStart, trans);
0644:
0645: RequestScope request = popRequest(session, ms);
0646: try {
0647: list = ms.executeQueryForList(request, trans,
0648: paramObject, skip, max);
0649: } finally {
0650: pushRequest(request);
0651: }
0652:
0653: autoCommitTransaction(session, autoStart);
0654: } finally {
0655: autoEndTransaction(session, autoStart);
0656: }
0657:
0658: return list;
0659: }
0660:
0661: /**
0662: * Execute a query with a row handler.
0663: * The row handler is called once per row in the query results.
0664: *
0665: * @param session - the session scope
0666: * @param id - the statement ID
0667: * @param paramObject - the parameter object
0668: * @param rowHandler - the row handler
0669: * @throws SQLException - if the query fails
0670: */
0671: public void queryWithRowHandler(SessionScope session, String id,
0672: Object paramObject, RowHandler rowHandler)
0673: throws SQLException {
0674:
0675: MappedStatement ms = getMappedStatement(id);
0676: Transaction trans = getTransaction(session);
0677: boolean autoStart = trans == null;
0678:
0679: try {
0680: trans = autoStartTransaction(session, autoStart, trans);
0681:
0682: RequestScope request = popRequest(session, ms);
0683: try {
0684: ms.executeQueryWithRowHandler(request, trans,
0685: paramObject, rowHandler);
0686: } finally {
0687: pushRequest(request);
0688: }
0689:
0690: autoCommitTransaction(session, autoStart);
0691: } finally {
0692: autoEndTransaction(session, autoStart);
0693: }
0694:
0695: }
0696:
0697: /**
0698: * Execute a query and return a paginated list
0699: *
0700: * @param session - the session scope
0701: * @param id - the statement ID
0702: * @param paramObject - the parameter object
0703: * @param pageSize - the page size
0704: * @return - the data list
0705: * @throws SQLException - if the query fails
0706: * @deprecated All paginated list features have been deprecated
0707: */
0708: public PaginatedList queryForPaginatedList(SessionScope session,
0709: String id, Object paramObject, int pageSize)
0710: throws SQLException {
0711: return new PaginatedDataList(session.getSqlMapExecutor(), id,
0712: paramObject, pageSize);
0713: }
0714:
0715: /**
0716: * Execute a query for a map.
0717: * The map has the table key as the key, and the results as the map data
0718: *
0719: * @param session - the session scope
0720: * @param id - the statement ID
0721: * @param paramObject - the parameter object
0722: * @param keyProp - the key property (from the results for the map)
0723: * @return - the Map
0724: * @throws SQLException - if the query fails
0725: */
0726: public Map queryForMap(SessionScope session, String id,
0727: Object paramObject, String keyProp) throws SQLException {
0728: return queryForMap(session, id, paramObject, keyProp, null);
0729: }
0730:
0731: /**
0732: * Execute a query for a map.
0733: * The map has the table key as the key, and a property from the results as the map data
0734: *
0735: * @param session - the session scope
0736: * @param id - the statement ID
0737: * @param paramObject - the parameter object
0738: * @param keyProp - the property for the map key
0739: * @param valueProp - the property for the map data
0740: * @return - the Map
0741: * @throws SQLException - if the query fails
0742: */
0743: public Map queryForMap(SessionScope session, String id,
0744: Object paramObject, String keyProp, String valueProp)
0745: throws SQLException {
0746: Map map = new HashMap();
0747:
0748: List list = queryForList(session, id, paramObject);
0749:
0750: for (int i = 0, n = list.size(); i < n; i++) {
0751: Object object = list.get(i);
0752: Object key = PROBE.getObject(object, keyProp);
0753: Object value = null;
0754: if (valueProp == null) {
0755: value = object;
0756: } else {
0757: value = PROBE.getObject(object, valueProp);
0758: }
0759: map.put(key, value);
0760: }
0761:
0762: return map;
0763: }
0764:
0765: // -- Transaction Control Methods
0766: /**
0767: * Start a transaction on the session
0768: *
0769: * @param session - the session
0770: * @throws SQLException - if the transaction could not be started
0771: */
0772: public void startTransaction(SessionScope session)
0773: throws SQLException {
0774: try {
0775: txManager.begin(session);
0776: } catch (TransactionException e) {
0777: throw new NestedSQLException(
0778: "Could not start transaction. Cause: " + e, e);
0779: }
0780: }
0781:
0782: /**
0783: * Start a transaction on the session with the specified isolation level.
0784: *
0785: * @param session - the session
0786: * @throws SQLException - if the transaction could not be started
0787: */
0788: public void startTransaction(SessionScope session,
0789: int transactionIsolation) throws SQLException {
0790: try {
0791: txManager.begin(session, transactionIsolation);
0792: } catch (TransactionException e) {
0793: throw new NestedSQLException(
0794: "Could not start transaction. Cause: " + e, e);
0795: }
0796: }
0797:
0798: /**
0799: * Commit the transaction on a session
0800: *
0801: * @param session - the session
0802: * @throws SQLException - if the transaction could not be committed
0803: */
0804: public void commitTransaction(SessionScope session)
0805: throws SQLException {
0806: try {
0807: // Auto batch execution
0808: if (session.isInBatch()) {
0809: executeBatch(session);
0810: }
0811: sqlExecutor.cleanup(session);
0812: txManager.commit(session);
0813: } catch (TransactionException e) {
0814: throw new NestedSQLException(
0815: "Could not commit transaction. Cause: " + e, e);
0816: }
0817: }
0818:
0819: /**
0820: * End the transaction on a session
0821: *
0822: * @param session - the session
0823: * @throws SQLException - if the transaction could not be ended
0824: */
0825: public void endTransaction(SessionScope session)
0826: throws SQLException {
0827: try {
0828: try {
0829: sqlExecutor.cleanup(session);
0830: } finally {
0831: txManager.end(session);
0832: }
0833: } catch (TransactionException e) {
0834: throw new NestedSQLException(
0835: "Error while ending transaction. Cause: " + e, e);
0836: }
0837: }
0838:
0839: /**
0840: * Start a batch for a session
0841: *
0842: * @param session - the session
0843: */
0844: public void startBatch(SessionScope session) {
0845: session.setInBatch(true);
0846: }
0847:
0848: /**
0849: * Execute a batch for a session
0850: *
0851: * @param session - the session
0852: * @return - the number of rows impacted by the batch
0853: * @throws SQLException - if the batch fails
0854: */
0855: public int executeBatch(SessionScope session) throws SQLException {
0856: session.setInBatch(false);
0857: return sqlExecutor.executeBatch(session);
0858: }
0859:
0860: /**
0861: * Execute a batch for a session
0862: *
0863: * @param session - the session
0864: * @return - a List of BatchResult objects (may be null if no batch
0865: * has been initiated). There will be one BatchResult object in the
0866: * list for each sub-batch executed
0867: * @throws SQLException if a database access error occurs, or the drive
0868: * does not support batch statements
0869: * @throws BatchException if the driver throws BatchUpdateException
0870: */
0871: public List executeBatchDetailed(SessionScope session)
0872: throws SQLException, BatchException {
0873: session.setInBatch(false);
0874: return sqlExecutor.executeBatchDetailed(session);
0875: }
0876:
0877: /**
0878: * Use a user-provided transaction for a session
0879: *
0880: * @param session - the session scope
0881: * @param userConnection - the user supplied connection
0882: */
0883: public void setUserProvidedTransaction(SessionScope session,
0884: Connection userConnection) {
0885: if (session.getTransactionState() == TransactionState.STATE_USER_PROVIDED) {
0886: session.recallTransactionState();
0887: }
0888: if (userConnection != null) {
0889: Connection conn = userConnection;
0890: session.saveTransactionState();
0891: session.setTransaction(new UserProvidedTransaction(conn));
0892: session
0893: .setTransactionState(TransactionState.STATE_USER_PROVIDED);
0894: } else {
0895: session.setTransaction(null);
0896: session.closePreparedStatements();
0897: session.reset(); // used to be pushSession, which is probably incorrect.
0898: }
0899: }
0900:
0901: /**
0902: * Get the DataSource for the session
0903: *
0904: * @return - the DataSource
0905: */
0906: public DataSource getDataSource() {
0907: DataSource ds = null;
0908: if (txManager != null) {
0909: ds = txManager.getDataSource();
0910: }
0911: return ds;
0912: }
0913:
0914: /**
0915: * Getter for the SqlExecutor
0916: *
0917: * @return the SqlExecutor
0918: */
0919: public SqlExecutor getSqlExecutor() {
0920: return sqlExecutor;
0921: }
0922:
0923: /**
0924: * Get a transaction for the session
0925: *
0926: * @param session - the session
0927: * @return - the transaction
0928: */
0929: public Transaction getTransaction(SessionScope session) {
0930: return session.getTransaction();
0931: }
0932:
0933: // -- Protected Methods
0934:
0935: protected void autoEndTransaction(SessionScope session,
0936: boolean autoStart) throws SQLException {
0937: if (autoStart) {
0938: session.getSqlMapTxMgr().endTransaction();
0939: }
0940: }
0941:
0942: protected void autoCommitTransaction(SessionScope session,
0943: boolean autoStart) throws SQLException {
0944: if (autoStart) {
0945: session.getSqlMapTxMgr().commitTransaction();
0946: }
0947: }
0948:
0949: protected Transaction autoStartTransaction(SessionScope session,
0950: boolean autoStart, Transaction trans) throws SQLException {
0951: Transaction transaction = trans;
0952: if (autoStart) {
0953: session.getSqlMapTxMgr().startTransaction();
0954: transaction = getTransaction(session);
0955: }
0956: return transaction;
0957: }
0958:
0959: public boolean equals(Object obj) {
0960: return this == obj;
0961: }
0962:
0963: public int hashCode() {
0964: CacheKey key = new CacheKey();
0965: if (txManager != null) {
0966: key.update(txManager);
0967: if (txManager.getDataSource() != null) {
0968: key.update(txManager.getDataSource());
0969: }
0970: }
0971: key.update(System.identityHashCode(this ));
0972: return key.hashCode();
0973: }
0974:
0975: protected RequestScope popRequest(SessionScope session,
0976: MappedStatement mappedStatement) {
0977: RequestScope request = (RequestScope) requestPool.pop();
0978: session.incrementRequestStackDepth();
0979: request.setSession(session);
0980: mappedStatement.initRequest(request);
0981: return request;
0982: }
0983:
0984: protected void pushRequest(RequestScope request) {
0985: request.getSession().decrementRequestStackDepth();
0986: request.reset();
0987: requestPool.push(request);
0988: }
0989:
0990: protected SessionScope popSession() {
0991: return (SessionScope) sessionPool.pop();
0992: }
0993:
0994: protected void pushSession(SessionScope session) {
0995: session.reset();
0996: sessionPool.push(session);
0997: }
0998:
0999: public ResultObjectFactory getResultObjectFactory() {
1000: return resultObjectFactory;
1001: }
1002:
1003: public void setResultObjectFactory(
1004: ResultObjectFactory resultObjectFactory) {
1005: this .resultObjectFactory = resultObjectFactory;
1006: }
1007:
1008: public boolean isStatementCacheEnabled() {
1009: return statementCacheEnabled;
1010: }
1011:
1012: public void setStatementCacheEnabled(boolean statementCacheEnabled) {
1013: this.statementCacheEnabled = statementCacheEnabled;
1014: }
1015: }
|