0001: /*
0002: * This file is part of the GeOxygene project source files.
0003: *
0004: * GeOxygene aims at providing an open framework which implements OGC/ISO specifications for
0005: * the development and deployment of geographic (GIS) applications. It is a open source
0006: * contribution of the COGIT laboratory at the Institut Géographique National (the French
0007: * National Mapping Agency).
0008: *
0009: * See: http://oxygene-project.sourceforge.net
0010: *
0011: * Copyright (C) 2005 Institut Géographique National
0012: *
0013: * This library is free software; you can redistribute it and/or modify it under the terms
0014: * of the GNU Lesser General Public License as published by the Free Software Foundation;
0015: * either version 2.1 of the License, or any later version.
0016: *
0017: * This library is distributed in the hope that it will be useful, but WITHOUT ANY
0018: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0019: * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
0020: *
0021: * You should have received a copy of the GNU Lesser General Public License along with
0022: * this library (see file LICENSE if present); if not, write to the Free Software
0023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0024: *
0025: */
0026:
0027: package fr.ign.cogit.geoxygene.datatools.ojb;
0028:
0029: import java.lang.reflect.Method;
0030: import java.sql.CallableStatement;
0031: import java.sql.Connection;
0032: import java.sql.PreparedStatement;
0033: import java.sql.ResultSet;
0034: import java.sql.SQLException;
0035: import java.sql.Statement;
0036: import java.sql.Types;
0037: import java.util.Collection;
0038: import java.util.Enumeration;
0039: import java.util.Iterator;
0040: import java.util.Map;
0041: import java.util.WeakHashMap;
0042:
0043: import org.apache.ojb.broker.Identity;
0044: import org.apache.ojb.broker.PersistenceBroker;
0045: import org.apache.ojb.broker.PersistenceBrokerException;
0046: import org.apache.ojb.broker.PersistenceBrokerSQLException;
0047: import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
0048: import org.apache.ojb.broker.accesslayer.LookupException;
0049: import org.apache.ojb.broker.accesslayer.StatementManager;
0050: import org.apache.ojb.broker.accesslayer.StatementManagerIF;
0051: import org.apache.ojb.broker.accesslayer.StatementsForClassFactory;
0052: import org.apache.ojb.broker.accesslayer.StatementsForClassIF;
0053: import org.apache.ojb.broker.core.ValueContainer;
0054: import org.apache.ojb.broker.metadata.ArgumentDescriptor;
0055: import org.apache.ojb.broker.metadata.ClassDescriptor;
0056: import org.apache.ojb.broker.metadata.FieldDescriptor;
0057: import org.apache.ojb.broker.metadata.ProcedureDescriptor;
0058: import org.apache.ojb.broker.platforms.Platform;
0059: import org.apache.ojb.broker.platforms.PlatformException;
0060: import org.apache.ojb.broker.platforms.PlatformFactory;
0061: import org.apache.ojb.broker.platforms.PlatformOracle9iImpl;
0062: import org.apache.ojb.broker.platforms.PlatformOracleImpl;
0063: import org.apache.ojb.broker.platforms.PlatformPostgreSQLImpl;
0064: import org.apache.ojb.broker.query.BetweenCriteria;
0065: import org.apache.ojb.broker.query.Criteria;
0066: import org.apache.ojb.broker.query.ExistsCriteria;
0067: import org.apache.ojb.broker.query.FieldCriteria;
0068: import org.apache.ojb.broker.query.InCriteria;
0069: import org.apache.ojb.broker.query.NullCriteria;
0070: import org.apache.ojb.broker.query.Query;
0071: import org.apache.ojb.broker.query.SelectionCriteria;
0072: import org.apache.ojb.broker.query.SqlCriteria;
0073: import org.apache.ojb.broker.util.JdbcTypesHelper;
0074: import org.apache.ojb.broker.util.logging.Logger;
0075: import org.apache.ojb.broker.util.logging.LoggerFactory;
0076: import org.postgis.PGgeometry;
0077:
0078: //import fr.ign.cogit.geoxygene.datatools.oracle.ArrayGeOxygene2Oracle;
0079: //import fr.ign.cogit.geoxygene.datatools.oracle.GeomGeOxygene2Oracle;
0080:
0081: /**
0082: * Meme chose que la classe org.apache.ojb.broker.accesslayer.StatementManager.
0083: * Permet de gerer les structures Oracle en passant un parametre de connection a un endroit.
0084: * Par rapport a la version originale de StatementManager :
0085: * les imports ont ete reorganises,
0086: * le constructeur renomme,
0087: * changement de la nature de l'attribut m_broker en GeOxygenePersistenceBrokerImpl,
0088: * changement d'une affectation de cet attribut dans le constructeur,
0089: * un ajout dans la methode bindStatementValue(),
0090: * changement dans getAllValues,
0091: * changement dans getKeyValues (2 methodes),
0092: * changement dans getNonKeyValues
0093: * modification des " setNull " (plusieurs) pour gerer le cas de l'ecriture de geometries nulles.
0094: *
0095: * AB 11 juillet 2005 :
0096: * <br> Utilisation des noms de classes et de la réflection pour permettre la compilation sépérée pour Oracle.
0097: * <br> Patch pour permettre l'utilisation de la meme classe de "FieldConversion" pour Oracle et Postgis.
0098: *
0099: * @author Thierry Badard & Arnaud Braun
0100: * @version 1.1
0101: *
0102: */
0103:
0104: public class GeOxygeneStatementManager implements StatementManagerIF {
0105: private Logger m_log = LoggerFactory
0106: .getLogger(StatementManager.class);
0107:
0108: /** internal table of StatementForClass objects */
0109: private Map m_statementTable = new WeakHashMap();
0110: /** the associated broker */
0111:
0112: // private final PersistenceBroker m_broker; initial OJB
0113: private final GeOxygenePersistenceBrokerImpl m_broker; // GeOxygene
0114:
0115: private Platform m_platform;
0116: /**
0117: * Used when OJB run in JBoss
0118: * Find a better solution to handle OJB within JBoss
0119: * --> the JCA implementation should solve this problem
0120: */
0121: private boolean m_eagerRelease;
0122: private ConnectionManagerIF m_conMan;
0123:
0124: // AJOUT pour GeOxygene ---------------------------------------------------
0125: // Nom des classes relatives à Oracle,
0126: //en String pour permettre la compilation séparée
0127: private final String GeomGeOxygene2Oracle_CLASS_NAME = "fr.ign.cogit.geoxygene.datatools.oracle.GeomGeOxygene2Oracle";
0128: private final String ArrayGeOxygene2Oracle_CLASS_NAME = "fr.ign.cogit.geoxygene.datatools.oracle.ArrayGeOxygene2Oracle";
0129: private final String GeomGeOxygene2Postgis_CLASS_NAME = "fr.ign.cogit.geoxygene.datatools.postgis.GeomGeOxygene2Postgis";
0130: private Class arrayGeOxygene2OracleClass;
0131: private Method geomGeOxygene2OracleMethod;
0132: private Method arrayGeOxygene2OracleMethod;
0133: private Method geomGeOxygene2PostgisMethod;
0134:
0135: // FIN AJOUT pour GeOxygene ---------------------------------------------------
0136:
0137: public GeOxygeneStatementManager(final PersistenceBroker pBroker) {
0138: // this.m_broker = pBroker; // initial OJB
0139: this .m_broker = (GeOxygenePersistenceBrokerImpl) pBroker; // GeOxygene
0140:
0141: this .m_conMan = m_broker.serviceConnectionManager();
0142: m_eagerRelease = m_conMan.getConnectionDescriptor()
0143: .getEagerRelease();
0144: m_platform = PlatformFactory.getPlatformFor(m_conMan
0145: .getConnectionDescriptor());
0146:
0147: // AJOUT pour GeOxygene -----------------------------------------------------------
0148: // ORACLE
0149: if (m_platform instanceof PlatformOracle9iImpl
0150: || m_platform instanceof PlatformOracleImpl)
0151: try {
0152: Class geomGeOxygene2OracleClass = Class
0153: .forName(GeomGeOxygene2Oracle_CLASS_NAME);
0154: arrayGeOxygene2OracleClass = Class
0155: .forName(ArrayGeOxygene2Oracle_CLASS_NAME);
0156: geomGeOxygene2OracleMethod = geomGeOxygene2OracleClass
0157: .getMethod("javaToSql", new Class[] {
0158: Object.class, Connection.class });
0159: arrayGeOxygene2OracleMethod = arrayGeOxygene2OracleClass
0160: .getMethod("javaToSql", new Class[] {
0161: Object.class, Connection.class });
0162: } catch (Exception e) {
0163: e.printStackTrace();
0164: }
0165:
0166: // POSTGIS
0167: else if (m_platform instanceof PlatformPostgreSQLImpl)
0168: try {
0169: Class geomGeOxygene2PostgisClass = Class
0170: .forName(GeomGeOxygene2Postgis_CLASS_NAME);
0171: geomGeOxygene2PostgisMethod = geomGeOxygene2PostgisClass
0172: .getMethod("javaToSql",
0173: new Class[] { Object.class });
0174: } catch (Exception e) {
0175: e.printStackTrace();
0176: }
0177:
0178: // AUTRE DBMS
0179: else {
0180: System.out
0181: .println("## Le SGBD n'est ni Oracle, ni PostgreSQL ##");
0182: System.out.println("## Le programme s'arrête ##");
0183: System.exit(0);
0184: }
0185: // FIN AJOUT pour GeOxygene ---------------------------------------------------
0186:
0187: }
0188:
0189: /**
0190: * return a StatementsForClass object for the given ClassDescriptor\
0191: * Note; not important to synchronize completely as a threading issue in this code
0192: * will only result in a little extra code being executed
0193: */
0194: protected StatementsForClassIF getStatementsForClass(
0195: ClassDescriptor cds) throws PersistenceBrokerException {
0196: StatementsForClassIF sfc = (StatementsForClassIF) m_statementTable
0197: .get(cds);
0198: if (sfc == null) {
0199: synchronized (m_statementTable) {
0200: // 07.17.2003 - RB: StatementsForClassImpl is now configurable
0201: //sfc = (StatementsForClassIF) new StatementsForClassImpl(m_conMan.getConnectionDescriptor(), cds);
0202: sfc = StatementsForClassFactory
0203: .getInstance()
0204: .getStatementsForClass(
0205: m_conMan.getConnectionDescriptor(), cds);
0206: m_statementTable.put(cds, sfc);
0207: }
0208: }
0209: return sfc;
0210: }
0211:
0212: public void closeResources(Statement stmt, ResultSet rs) {
0213: if (m_log.isDebugEnabled())
0214: m_log.debug("closeResources was called");
0215: try {
0216: m_platform.beforeStatementClose(stmt, rs);
0217: //close statement on wrapped statement class, or real statement
0218: if (stmt != null) {
0219: //log.info("## close: "+stmt);
0220: stmt.close();
0221:
0222: /*
0223: *********************************************
0224: special stuff for OJB within JBoss
0225: ********************************************
0226: */
0227: if (m_eagerRelease) {
0228: m_conMan.releaseConnection();
0229: }
0230:
0231: }
0232: m_platform.afterStatementClose(stmt, rs);
0233: } catch (PlatformException e) {
0234: m_log.error("Platform dependent operation failed", e);
0235: } catch (SQLException ignored) {
0236: if (m_log.isDebugEnabled())
0237: m_log.debug("Statement closing failed", ignored);
0238: }
0239: }
0240:
0241: /**
0242: * binds the Identities Primary key values to the statement
0243: */
0244: public void bindDelete(PreparedStatement stmt, Identity oid,
0245: ClassDescriptor cld) throws SQLException {
0246: Object[] pkValues = oid.getPrimaryKeyValues();
0247: FieldDescriptor[] pkFields = cld.getPkFields();
0248: int i = 0;
0249: try {
0250: for (; i < pkValues.length; i++) {
0251: m_platform.setObjectForStatement(stmt, i + 1,
0252: pkValues[i], pkFields[i].getJdbcType()
0253: .getType());
0254: }
0255: } catch (SQLException e) {
0256: m_log.error("bindDelete failed for: " + oid.toString()
0257: + ", while set value '" + pkValues[i]
0258: + "' for column " + pkFields[i].getColumnName());
0259: throw e;
0260: }
0261: }
0262:
0263: /**
0264: * binds the objects primary key and locking values to the statement, BRJ
0265: */
0266: public void bindDelete(PreparedStatement stmt, ClassDescriptor cld,
0267: Object obj) throws SQLException {
0268: if (cld.getDeleteProcedure() != null) {
0269: this
0270: .bindProcedure(stmt, cld, obj, cld
0271: .getDeleteProcedure());
0272: } else {
0273: int index = 1;
0274: ValueContainer[] values, currentLockingValues;
0275:
0276: currentLockingValues = cld.getCurrentLockingValues(obj);
0277: // parameters for WHERE-clause pk
0278: values = getKeyValues(m_broker, cld, obj);
0279: for (int i = 0; i < values.length; i++) {
0280: m_platform.setObjectForStatement(stmt, index, values[i]
0281: .getValue(), values[i].getJdbcType().getType());
0282: index++;
0283: }
0284:
0285: // parameters for WHERE-clause locking
0286: values = currentLockingValues;
0287: for (int i = 0; i < values.length; i++) {
0288: m_platform.setObjectForStatement(stmt, index, values[i]
0289: .getValue(), values[i].getJdbcType().getType());
0290: index++;
0291: }
0292: }
0293: }
0294:
0295: /**
0296: * bind attribute and value
0297: * @param stmt
0298: * @param index
0299: * @param attributeOrQuery
0300: * @param value
0301: * @param cld
0302: * @return
0303: * @throws SQLException
0304: */
0305: private int bindStatementValue(PreparedStatement stmt, int index,
0306: Object attributeOrQuery, Object value, ClassDescriptor cld)
0307: throws SQLException {
0308: FieldDescriptor fld = null;
0309: // if value is a subQuery bind it
0310: if (value instanceof Query) {
0311: Query subQuery = (Query) value;
0312: return bindStatement(stmt, subQuery, cld.getRepository()
0313: .getDescriptorFor(subQuery.getSearchClass()), index);
0314: }
0315:
0316: // if attribute is a subQuery bind it
0317: if (attributeOrQuery instanceof Query) {
0318: Query subQuery = (Query) attributeOrQuery;
0319: bindStatement(stmt, subQuery, cld.getRepository()
0320: .getDescriptorFor(subQuery.getSearchClass()), index);
0321: } else {
0322: fld = cld
0323: .getFieldDescriptorForPath((String) attributeOrQuery);
0324: }
0325:
0326: if (fld != null) {
0327: // BRJ: use field conversions and platform
0328: if (value != null) {
0329: // ======= DEBUT AJOUT POUR GeOxygene ====================
0330: // Gestion des géométrie
0331: if (fld.getFieldConversion() instanceof GeomGeOxygene2Dbms) {
0332: // ORACLE
0333: if (m_platform instanceof PlatformOracle9iImpl
0334: || m_platform instanceof PlatformOracleImpl) {
0335: try {
0336: Object sql = geomGeOxygene2OracleMethod
0337: .invoke(
0338: fld.getFieldConversion(),
0339: new Object[] {
0340: value,
0341: stmt
0342: .getConnection() });
0343: m_platform.setObjectForStatement(stmt,
0344: index, sql, Types.STRUCT);
0345: } catch (Exception e) {
0346: e.printStackTrace();
0347: }
0348: } // POSTGIS
0349: if (m_platform instanceof PlatformPostgreSQLImpl) {
0350: try {
0351: Object sql = geomGeOxygene2PostgisMethod
0352: .invoke(fld.getFieldConversion(),
0353: new Object[] { value });
0354: m_platform.setObjectForStatement(stmt,
0355: index, sql, Types.CHAR);
0356: } catch (Exception e) {
0357: e.printStackTrace();
0358: }
0359: }
0360:
0361: // Gestion des tableaux
0362: } else if (fld.getFieldConversion().getClass() == arrayGeOxygene2OracleClass) {
0363: try {
0364: Object sql = arrayGeOxygene2OracleMethod
0365: .invoke(fld.getFieldConversion(),
0366: new Object[] { value,
0367: stmt.getConnection() });
0368: m_platform.setObjectForStatement(stmt, index,
0369: sql, Types.ARRAY);
0370: } catch (Exception e) {
0371: e.printStackTrace();
0372: }
0373: } else
0374: // ======= FIN AJOUT POUR GeOxygene ======================
0375: // S'applique aux types d'objets standards (ni geometrie, ni tableau)
0376:
0377: m_platform.setObjectForStatement(stmt, index, fld
0378: .getFieldConversion().javaToSql(value), fld
0379: .getJdbcType().getType());
0380: } else {
0381: // ======= DEBUT AJOUT POUR GeOxygene ====================
0382: // Gestion des géométries nulles sous Oracle (plante sinon)
0383: if (fld.getJdbcType().getType() == Types.STRUCT)
0384: try {
0385: stmt.setNull(index,
0386: fld.getJdbcType().getType(),
0387: "MDSYS.SDO_GEOMETRY");
0388: } catch (Exception e) {
0389: e.printStackTrace();
0390: }
0391: else
0392: // ======= FIN AJOUT POUR GeOxygene ====================
0393:
0394: m_platform.setNullForStatement(stmt, index, fld
0395: .getJdbcType().getType());
0396: }
0397: } else {
0398: if (value != null) {
0399: stmt.setObject(index, value);
0400: } else {
0401: stmt.setNull(index, Types.NULL);
0402: }
0403: }
0404:
0405: return ++index; // increment before return
0406: }
0407:
0408: /**
0409: * bind SelectionCriteria
0410: * @param stmt the PreparedStatement
0411: * @param index the position of the parameter to bind
0412: * @param crit the Criteria containing the parameter
0413: * @param cld the ClassDescriptor
0414: * @return next index for PreparedStatement
0415: */
0416: private int bindStatement(PreparedStatement stmt, int index,
0417: SelectionCriteria crit, ClassDescriptor cld)
0418: throws SQLException {
0419: return bindStatementValue(stmt, index, crit.getAttribute(),
0420: crit.getValue(), cld);
0421: }
0422:
0423: /**
0424: * bind NullCriteria
0425: * @param stmt the PreparedStatement
0426: * @param index the position of the parameter to bind
0427: * @param crit the Criteria containing the parameter
0428: * @return next index for PreparedStatement
0429: */
0430: private int bindStatement(PreparedStatement stmt, int index,
0431: NullCriteria crit) throws SQLException {
0432: return index;
0433: }
0434:
0435: /**
0436: * bind FieldCriteria
0437: * @param stmt , the PreparedStatement
0438: * @param index , the position of the parameter to bind
0439: * @param crit , the Criteria containing the parameter
0440: * @return next index for PreparedStatement
0441: */
0442: private int bindStatement(PreparedStatement stmt, int index,
0443: FieldCriteria crit) throws SQLException {
0444: return index;
0445: }
0446:
0447: /**
0448: * bind SqlCriteria
0449: * @param stmt the PreparedStatement
0450: * @param index the position of the parameter to bind
0451: * @param crit the Criteria containing the parameter
0452: * @return next index for PreparedStatement
0453: */
0454: private int bindStatement(PreparedStatement stmt, int index,
0455: SqlCriteria crit) throws SQLException {
0456: return index;
0457: }
0458:
0459: /**
0460: * bind BetweenCriteria
0461: * @param stmt the PreparedStatement
0462: * @param index the position of the parameter to bind
0463: * @param crit the Criteria containing the parameter
0464: * @param cld the ClassDescriptor
0465: * @return next index for PreparedStatement
0466: */
0467: private int bindStatement(PreparedStatement stmt, int index,
0468: BetweenCriteria crit, ClassDescriptor cld)
0469: throws SQLException {
0470: index = bindStatementValue(stmt, index, crit.getAttribute(),
0471: crit.getValue(), cld);
0472:
0473: return bindStatementValue(stmt, index, crit.getAttribute(),
0474: crit.getValue2(), cld);
0475: }
0476:
0477: /**
0478: * bind InCriteria
0479: * @param stmt the PreparedStatement
0480: * @param index the position of the parameter to bind
0481: * @param crit the Criteria containing the parameter
0482: * @param cld the ClassDescriptor
0483: * @return next index for PreparedStatement
0484: */
0485: private int bindStatement(PreparedStatement stmt, int index,
0486: InCriteria crit, ClassDescriptor cld) throws SQLException {
0487: if (crit.getValue() instanceof Collection) {
0488: Collection values = (Collection) crit.getValue();
0489: Iterator iter = values.iterator();
0490:
0491: while (iter.hasNext()) {
0492: index = bindStatementValue(stmt, index, crit
0493: .getAttribute(), iter.next(), cld);
0494: }
0495: } else {
0496: index = bindStatementValue(stmt, index,
0497: crit.getAttribute(), crit.getValue(), cld);
0498: }
0499: return index;
0500: }
0501:
0502: /**
0503: * bind ExistsCriteria
0504: * @param stmt the PreparedStatement
0505: * @param index the position of the parameter to bind
0506: * @param crit the Criteria containing the parameter
0507: * @param cld the ClassDescriptor
0508: * @return next index for PreparedStatement
0509: */
0510: private int bindStatement(PreparedStatement stmt, int index,
0511: ExistsCriteria crit, ClassDescriptor cld)
0512: throws SQLException {
0513: Query subQuery = (Query) crit.getValue();
0514:
0515: // if query has criteria, bind them
0516: if (subQuery.getCriteria() != null
0517: && !subQuery.getCriteria().isEmpty()) {
0518: return bindStatement(stmt, subQuery.getCriteria(), cld
0519: .getRepository().getDescriptorFor(
0520: subQuery.getSearchClass()), index);
0521:
0522: // otherwise, just ignore it
0523: } else {
0524: return index;
0525: }
0526: }
0527:
0528: /**
0529: * bind a Query based Select Statement
0530: */
0531: public int bindStatement(PreparedStatement stmt, Query query,
0532: ClassDescriptor cld, int param) throws SQLException {
0533: int result;
0534:
0535: result = bindStatement(stmt, query.getCriteria(), cld, param);
0536: result = bindStatement(stmt, query.getHavingCriteria(), cld,
0537: result);
0538:
0539: return result;
0540: }
0541:
0542: /**
0543: * bind a Query based Select Statement
0544: */
0545: protected int bindStatement(PreparedStatement stmt, Criteria crit,
0546: ClassDescriptor cld, int param) throws SQLException {
0547: if (crit != null) {
0548: Enumeration e = crit.getElements();
0549:
0550: while (e.hasMoreElements()) {
0551: Object o = e.nextElement();
0552: if (o instanceof Criteria) {
0553: Criteria pc = (Criteria) o;
0554: param = bindStatement(stmt, pc, cld, param);
0555: } else {
0556: SelectionCriteria c = (SelectionCriteria) o;
0557: // BRJ : bind once for the criterion's main class
0558: param = bindSelectionCriteria(stmt, param, c, cld);
0559:
0560: // BRJ : and once for each extent
0561: for (int i = 0; i < c.getNumberOfExtentsToBind(); i++) {
0562: param = bindSelectionCriteria(stmt, param, c,
0563: cld);
0564: }
0565: }
0566: }
0567: }
0568: return param;
0569: }
0570:
0571: /**
0572: * bind SelectionCriteria
0573: * @param stmt the PreparedStatement
0574: * @param index the position of the parameter to bind
0575: * @param crit the Criteria containing the parameter
0576: * @param cld the ClassDescriptor
0577: * @return next index for PreparedStatement
0578: */
0579: private int bindSelectionCriteria(PreparedStatement stmt,
0580: int index, SelectionCriteria crit, ClassDescriptor cld)
0581: throws SQLException {
0582: if (crit instanceof NullCriteria)
0583: index = bindStatement(stmt, index, (NullCriteria) crit);
0584: else if (crit instanceof BetweenCriteria)
0585: index = bindStatement(stmt, index, (BetweenCriteria) crit,
0586: cld);
0587: else if (crit instanceof InCriteria)
0588: index = bindStatement(stmt, index, (InCriteria) crit, cld);
0589: else if (crit instanceof SqlCriteria)
0590: index = bindStatement(stmt, index, (SqlCriteria) crit);
0591: else if (crit instanceof FieldCriteria)
0592: index = bindStatement(stmt, index, (FieldCriteria) crit);
0593: else if (crit instanceof ExistsCriteria)
0594: index = bindStatement(stmt, index, (ExistsCriteria) crit,
0595: cld);
0596: else
0597: index = bindStatement(stmt, index, crit, cld);
0598:
0599: return index;
0600: }
0601:
0602: /**
0603: * binds the values of the object obj to the statements parameters
0604: */
0605: public void bindInsert(PreparedStatement stmt, ClassDescriptor cld,
0606: Object obj) throws java.sql.SQLException {
0607: ValueContainer[] values;
0608: cld.updateLockingValues(obj); // BRJ : provide useful defaults for locking fields
0609:
0610: if (cld.getInsertProcedure() != null) {
0611: this
0612: .bindProcedure(stmt, cld, obj, cld
0613: .getInsertProcedure());
0614: } else {
0615: values = getAllValues(cld, obj);
0616: for (int i = 0; i < values.length; i++) {
0617: ValueContainer val = values[i];
0618:
0619: // DEBUT AJOUT POUR GEOXYGENE ----------------------------------------------
0620: // Pour PostGIS le type JDBC STRUC n'est pas reconnu
0621: // On caste en un autre type (OTHER)
0622: // qui a été ajouté dans le "JDBCTypesHelper" réécrit pour l'occasion
0623: // ( ce type n'existe pas dans OJB par défaut)
0624: if (val.getValue() instanceof PGgeometry)
0625: val.setJdbcType(JdbcTypesHelper
0626: .getJdbcTypeByName("other"));
0627: // FIN AJOUT POUR GEOXYGENE ----------------------------------------------
0628:
0629: if (val.getValue() != null) {
0630: m_platform.setObjectForStatement(stmt, i + 1, val
0631: .getValue(), val.getJdbcType().getType());
0632: } else {
0633: // ======= DEBUT AJOUT POUR GeOxygene ====================
0634: // Gestion des géométries nulles sous Oracle (plante sinon)
0635: if (val.getJdbcType().getType() == Types.STRUCT)
0636: try {
0637: stmt.setNull(i + 1, val.getJdbcType()
0638: .getType(), "MDSYS.SDO_GEOMETRY");
0639: } catch (Exception e) {
0640: e.printStackTrace();
0641: }
0642: else
0643: // ======= FIN AJOUT POUR GeOxygene ====================
0644:
0645: m_platform.setNullForStatement(stmt, i + 1, val
0646: .getJdbcType().getType());
0647: }
0648: }
0649: }
0650: }
0651:
0652: /**
0653: * binds the Identities Primary key values to the statement
0654: */
0655: public void bindSelect(PreparedStatement stmt, Identity oid,
0656: ClassDescriptor cld) throws SQLException {
0657: ValueContainer[] values = null;
0658: int i = 0;
0659:
0660: if (cld == null) {
0661: cld = m_broker
0662: .getClassDescriptor(oid.getObjectsRealClass());
0663: }
0664: try {
0665: values = getKeyValues(m_broker, cld, oid);
0666: for (i = 0; i < values.length; i++) {
0667: ValueContainer valContainer = values[i];
0668: if (valContainer.getValue() != null) {
0669: m_platform.setObjectForStatement(stmt, i + 1,
0670: valContainer.getValue(), valContainer
0671: .getJdbcType().getType());
0672: } else {
0673: m_platform.setNullForStatement(stmt, i + 1,
0674: valContainer.getJdbcType().getType());
0675: }
0676: }
0677: } catch (SQLException e) {
0678: m_log.error("bindSelect failed for: " + oid.toString()
0679: + ", PK: " + i + ", value: " + values[i]);
0680: throw e;
0681: }
0682: }
0683:
0684: /**
0685: * binds the values of the object obj to the statements parameters
0686: */
0687: public void bindUpdate(PreparedStatement stmt, ClassDescriptor cld,
0688: Object obj) throws java.sql.SQLException {
0689: if (cld.getUpdateProcedure() != null) {
0690: this
0691: .bindProcedure(stmt, cld, obj, cld
0692: .getUpdateProcedure());
0693: } else {
0694: int index = 1;
0695: ValueContainer[] values, valuesSnapshot;
0696: // first take a snapshot of current locking values
0697: valuesSnapshot = cld.getCurrentLockingValues(obj);
0698: cld.updateLockingValues(obj); // BRJ
0699: values = getNonKeyValues(m_broker, cld, obj);
0700:
0701: // parameters for SET-clause
0702: for (int i = 0; i < values.length; i++) {
0703:
0704: // DEBUT AJOUT POUR GEOXYGENE ----------------------------------------------
0705: // Pour PostGIS le type JDBC STRUC n'est pas reconnu
0706: // On caste en un autre type (OTHER)
0707: // qui a été ajouté dans le "JDBCTypesHelper" réécrit pour l'occasion
0708: // ( ce type n'existe pas dans OJB par défaut)
0709: if (values[i].getValue() instanceof PGgeometry)
0710: values[i].setJdbcType(JdbcTypesHelper
0711: .getJdbcTypeByName("other"));
0712: // FIN AJOUT POUR GEOXYGENE ----------------------------------------------
0713:
0714: if (values[i].getValue() != null) {
0715: m_platform.setObjectForStatement(stmt, index,
0716: values[i].getValue(), values[i]
0717: .getJdbcType().getType());
0718: } else {
0719: // ======= DEBUT AJOUT POUR GeOxygene ====================
0720: // Gestion des géométries nulles sous Oracle (plante sinon)
0721: if (values[i].getJdbcType().getType() == Types.STRUCT)
0722: try {
0723: stmt.setNull(index, values[i].getJdbcType()
0724: .getType(), "MDSYS.SDO_GEOMETRY");
0725: } catch (Exception e) {
0726: e.printStackTrace();
0727: }
0728: else
0729: // ======= FIN AJOUT POUR GeOxygene ====================
0730:
0731: m_platform.setNullForStatement(stmt, index,
0732: values[i].getJdbcType().getType());
0733: }
0734:
0735: index++;
0736: }
0737: // parameters for WHERE-clause pk
0738: values = getKeyValues(m_broker, cld, obj);
0739: for (int i = 0; i < values.length; i++) {
0740: if (values[i].getValue() != null) {
0741: stmt.setObject(index, values[i].getValue(),
0742: values[i].getJdbcType().getType());
0743: } else {
0744: stmt.setNull(index, values[i].getJdbcType()
0745: .getType());
0746: }
0747: index++;
0748: }
0749: // parameters for WHERE-clause locking
0750: // take old locking values
0751: values = valuesSnapshot;
0752: for (int i = 0; i < values.length; i++) {
0753: if (values[i].getValue() != null) {
0754: stmt.setObject(index, values[i].getValue(),
0755: values[i].getJdbcType().getType());
0756: } else {
0757: // ======= DEBUT AJOUT POUR GeOxygene ====================
0758: // Gestion des géométries nulles sous Oracle (plante sinon)
0759: if (values[i].getJdbcType().getType() == Types.STRUCT)
0760: try {
0761: stmt.setNull(index, values[i].getJdbcType()
0762: .getType(), "MDSYS.SDO_GEOMETRY");
0763: } catch (Exception e) {
0764: e.printStackTrace();
0765: }
0766: else
0767: // ======= FIN AJOUT POUR GeOxygene ====================
0768:
0769: stmt.setNull(index, values[i].getJdbcType()
0770: .getType());
0771: }
0772: index++;
0773: }
0774: }
0775: }
0776:
0777: /**
0778: * binds the given array of values (if not null) starting from the given
0779: * parameter index
0780: * @return the next parameter index
0781: */
0782: public int bindValues(PreparedStatement stmt,
0783: ValueContainer[] values, int index) throws SQLException {
0784: if (values != null) {
0785: for (int i = 0; i < values.length; i++) {
0786: m_platform.setObjectForStatement(stmt, index, values[i]
0787: .getValue(), values[i].getJdbcType().getType());
0788: index++;
0789: }
0790: }
0791: return index;
0792: }
0793:
0794: /**
0795: * return a prepared DELETE Statement fitting for the given ClassDescriptor
0796: */
0797: public PreparedStatement getDeleteStatement(ClassDescriptor cld)
0798: throws PersistenceBrokerSQLException,
0799: PersistenceBrokerException {
0800: try {
0801: return getStatementsForClass(cld).getDeleteStmt(
0802: m_conMan.getConnection());
0803: } catch (SQLException e) {
0804: throw new PersistenceBrokerSQLException(
0805: "Could not build statement ask for", e);
0806: } catch (LookupException e) {
0807: throw new PersistenceBrokerException(
0808: "Used ConnectionManager instance could not obtain a connection",
0809: e);
0810: }
0811: }
0812:
0813: /**
0814: * return a generic Statement for the given ClassDescriptor.
0815: * Never use this method for UPDATE/INSERT/DELETE if you want to use the batch mode.
0816: */
0817: public Statement getGenericStatement(ClassDescriptor cds,
0818: boolean scrollable) throws PersistenceBrokerException {
0819: try {
0820: return getStatementsForClass(cds).getGenericStmt(
0821: m_conMan.getConnection(), scrollable);
0822: } catch (LookupException e) {
0823: throw new PersistenceBrokerException(
0824: "Used ConnectionManager instance could not obtain a connection",
0825: e);
0826: }
0827: }
0828:
0829: /**
0830: * return a prepared Insert Statement fitting for the given ClassDescriptor
0831: */
0832: public PreparedStatement getInsertStatement(ClassDescriptor cds)
0833: throws PersistenceBrokerSQLException,
0834: PersistenceBrokerException {
0835: try {
0836: return getStatementsForClass(cds).getInsertStmt(
0837: m_conMan.getConnection());
0838: } catch (SQLException e) {
0839: throw new PersistenceBrokerSQLException(
0840: "Could not build statement ask for", e);
0841: } catch (LookupException e) {
0842: throw new PersistenceBrokerException(
0843: "Used ConnectionManager instance could not obtain a connection",
0844: e);
0845: }
0846: }
0847:
0848: /**
0849: * return a generic Statement for the given ClassDescriptor
0850: */
0851: public PreparedStatement getPreparedStatement(ClassDescriptor cds,
0852: String sql, boolean scrollable)
0853: throws PersistenceBrokerException {
0854: try {
0855: return getStatementsForClass(cds).getPreparedStmt(
0856: m_conMan.getConnection(), sql, scrollable);
0857: } catch (LookupException e) {
0858: throw new PersistenceBrokerException(
0859: "Used ConnectionManager instance could not obtain a connection",
0860: e);
0861: }
0862: }
0863:
0864: /**
0865: * return a prepared Select Statement for the given ClassDescriptor
0866: */
0867: public PreparedStatement getSelectByPKStatement(ClassDescriptor cds)
0868: throws PersistenceBrokerSQLException,
0869: PersistenceBrokerException {
0870: try {
0871: return getStatementsForClass(cds).getSelectByPKStmt(
0872: m_conMan.getConnection());
0873: } catch (SQLException e) {
0874: throw new PersistenceBrokerSQLException(
0875: "Could not build statement ask for", e);
0876: } catch (LookupException e) {
0877: throw new PersistenceBrokerException(
0878: "Used ConnectionManager instance could not obtain a connection",
0879: e);
0880: }
0881: }
0882:
0883: /**
0884: * return a prepared Update Statement fitting to the given ClassDescriptor
0885: */
0886: public PreparedStatement getUpdateStatement(ClassDescriptor cds)
0887: throws PersistenceBrokerSQLException,
0888: PersistenceBrokerException {
0889: try {
0890: return getStatementsForClass(cds).getUpdateStmt(
0891: m_conMan.getConnection());
0892: } catch (SQLException e) {
0893: throw new PersistenceBrokerSQLException(
0894: "Could not build statement ask for", e);
0895: } catch (LookupException e) {
0896: throw new PersistenceBrokerException(
0897: "Used ConnectionManager instance could not obtain a connection",
0898: e);
0899: }
0900: }
0901:
0902: /**
0903: * returns an array containing values for all the Objects attribute
0904: * @throws PersistenceBrokerException if there is an erros accessing obj field values
0905: */
0906: protected ValueContainer[] getAllValues(ClassDescriptor cld,
0907: Object obj) throws PersistenceBrokerException {
0908: Connection conn = null;
0909: try {
0910: conn = m_broker.serviceConnectionManager().getConnection();
0911: } catch (Exception e) {
0912: e.printStackTrace();
0913: }
0914:
0915: return m_broker.serviceOxygeneBrokerHelper().getAllRwValues(
0916: cld, obj, conn);
0917: }
0918:
0919: /**
0920: * returns an Array with an Objects PK VALUES
0921: * @throws PersistenceBrokerException if there is an erros accessing o field values
0922: */
0923: protected ValueContainer[] getKeyValues(PersistenceBroker broker,
0924: ClassDescriptor cld, Object obj)
0925: throws PersistenceBrokerException {
0926: GeOxygenePersistenceBrokerImpl geOxyBroker = (GeOxygenePersistenceBrokerImpl) broker;
0927: Connection conn = null;
0928: try {
0929: conn = geOxyBroker.serviceConnectionManager()
0930: .getConnection();
0931: } catch (Exception e) {
0932: e.printStackTrace();
0933: }
0934:
0935: return (geOxyBroker.serviceOxygeneBrokerHelper().getKeyValues(
0936: cld, obj, conn));
0937: }
0938:
0939: /**
0940: * returns an Array with an Identities PK VALUES
0941: * @throws PersistenceBrokerException if there is an erros accessing o field values
0942: */
0943: protected ValueContainer[] getKeyValues(PersistenceBroker broker,
0944: ClassDescriptor cld, Identity oid)
0945: throws PersistenceBrokerException {
0946: GeOxygenePersistenceBrokerImpl geOxyBroker = (GeOxygenePersistenceBrokerImpl) broker;
0947: Connection conn = null;
0948: try {
0949: conn = geOxyBroker.serviceConnectionManager()
0950: .getConnection();
0951: } catch (Exception e) {
0952: e.printStackTrace();
0953: }
0954:
0955: return (geOxyBroker.serviceOxygeneBrokerHelper().getKeyValues(
0956: cld, oid));
0957: }
0958:
0959: /**
0960: * returns an Array with an Objects NON-PK VALUES
0961: * @throws PersistenceBrokerException if there is an erros accessing o field values
0962: */
0963: protected ValueContainer[] getNonKeyValues(
0964: PersistenceBroker broker, ClassDescriptor cld, Object obj)
0965: throws PersistenceBrokerException {
0966: GeOxygenePersistenceBrokerImpl geOxyBroker = (GeOxygenePersistenceBrokerImpl) broker;
0967: Connection conn = null;
0968: try {
0969: conn = geOxyBroker.serviceConnectionManager()
0970: .getConnection();
0971: } catch (Exception e) {
0972: e.printStackTrace();
0973: }
0974:
0975: return (geOxyBroker.serviceOxygeneBrokerHelper()
0976: .getNonKeyRwValues(cld, obj, conn));
0977: }
0978:
0979: /**
0980: * Bind a prepared statment that represents a call to a procedure or
0981: * user-defined function.
0982: *
0983: * @param stmt the statement to bind.
0984: * @param cld the class descriptor of the object that triggered the
0985: * invocation of the procedure or user-defined function.
0986: * @param obj the object that triggered the invocation of the procedure
0987: * or user-defined function.
0988: * @param proc the procedure descriptor that provides information about
0989: * the arguments that shoudl be passed to the procedure or
0990: * user-defined function
0991: */
0992: private void bindProcedure(PreparedStatement stmt,
0993: ClassDescriptor cld, Object obj, ProcedureDescriptor proc)
0994: throws SQLException {
0995: int valueSub = 0;
0996:
0997: // Figure out if we are using a callable statement. If we are, then we
0998: // will need to register one or more output parameters.
0999: CallableStatement callable = null;
1000: if (stmt instanceof CallableStatement) {
1001: callable = (CallableStatement) stmt;
1002: }
1003:
1004: // If we have a return value, then register it.
1005: if ((proc.hasReturnValue()) && (callable != null)) {
1006: int jdbcType = proc.getReturnValueFieldRef().getJdbcType()
1007: .getType();
1008: m_platform
1009: .setNullForStatement(stmt, valueSub + 1, jdbcType);
1010: callable.registerOutParameter(valueSub + 1, jdbcType);
1011: valueSub++;
1012: }
1013:
1014: // Process all of the arguments.
1015: Iterator iterator = proc.getArguments().iterator();
1016: while (iterator.hasNext()) {
1017: ArgumentDescriptor arg = (ArgumentDescriptor) iterator
1018: .next();
1019: Object val = arg.getValue(obj);
1020: int jdbcType = arg.getJdbcType();
1021: if (val != null) {
1022: m_platform.setObjectForStatement(stmt, valueSub + 1,
1023: val, jdbcType);
1024: } else {
1025: m_platform.setNullForStatement(stmt, valueSub + 1,
1026: jdbcType);
1027: }
1028: if ((arg.getIsReturnedByProcedure()) && (callable != null)) {
1029: callable.registerOutParameter(valueSub + 1, jdbcType);
1030: }
1031: valueSub++;
1032: }
1033: }
1034: }
|