001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data.oracle;
017:
018: import java.io.IOException;
019: import java.sql.Connection;
020: import java.sql.PreparedStatement;
021: import java.sql.SQLException;
022: import java.sql.Statement;
023: import java.util.logging.Level;
024: import java.util.logging.Logger;
025:
026: import oracle.jdbc.OracleConnection;
027: import oracle.sql.STRUCT;
028:
029: import org.geotools.data.DataSourceException;
030: import org.geotools.data.DataUtilities;
031: import org.geotools.data.FeatureReader;
032: import org.geotools.data.jdbc.JDBCTextFeatureWriter;
033: import org.geotools.data.jdbc.MutableFIDFeature;
034: import org.geotools.data.jdbc.QueryData;
035: import org.geotools.data.jdbc.datasource.DataSourceFinder;
036: import org.geotools.data.jdbc.datasource.UnWrapper;
037: import org.geotools.data.oracle.sdo.GeometryConverter;
038: import org.geotools.feature.AttributeType;
039: import org.geotools.feature.Feature;
040: import org.geotools.feature.FeatureType;
041: import org.geotools.feature.type.GeometricAttributeType;
042: import org.geotools.filter.SQLEncoderOracle;
043:
044: import com.vividsolutions.jts.geom.Geometry;
045:
046: /**
047: * Subclasses JDBCTextFeatureWriter to issue Oracle transactions directly as
048: * sql text statements. The super class takes care of all the nasty details,
049: * this just returns the encoded geometry. To get some speed increases Jody
050: * maintains that this class should not be used, that the updatable result
051: * sets of JDBCFeatureWriter will work better. But I couldn't get those to
052: * work at all, whereas this works great for me. We could also consider
053: * putting the option for this or jdbc in the factory for OracleDataStore.
054: * Should also consider using prepared statements for inserts, as they should
055: * work faster - this should probably be done in the superclass.
056: *
057: * @author Chris Holmes, TOPP
058: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/oracle-spatial/src/main/java/org/geotools/data/oracle/OracleFeatureWriter.java $
059: * @version $Id: OracleFeatureWriter.java 27862 2007-11-12 19:51:19Z desruisseaux $
060: */
061: public class OracleFeatureWriter extends JDBCTextFeatureWriter {
062: private static final Logger LOGGER = org.geotools.util.logging.Logging
063: .getLogger("org.geotools.data.oracle");
064:
065: GeometryConverter converter;
066:
067: public OracleFeatureWriter(FeatureReader fReader,
068: QueryData queryData) throws IOException {
069: super (fReader, queryData);
070: Connection conn = queryData.getConnection();
071: if (!(conn instanceof OracleConnection)) {
072: UnWrapper uw = DataSourceFinder.getUnWrapper(conn);
073: if (uw != null)
074: conn = uw.unwrap(conn);
075: }
076: OracleConnection oracleConnection = (OracleConnection) conn;
077: this .converter = new GeometryConverter(oracleConnection);
078: }
079:
080: protected String getGeometryInsertText(Geometry geom, int srid)
081: throws IOException {
082: return "?"; // Please use a prepaired statement to insert your geometry
083:
084: //String geomText = SQLEncoderOracle.toSDOGeom(geom, srid);
085: //return geomText;
086: }
087:
088: /**
089: * Override that uses sql statements to perform the operation.
090: *
091: * @see org.geotools.data.jdbc.JDBCFeatureWriter#doUpdate(org.geotools.feature.Feature,
092: * org.geotools.feature.Feature)
093: */
094: protected void doUpdate(Feature live, Feature current)
095: throws IOException, SQLException {
096: if (LOGGER.isLoggable(Level.FINE)) {
097: LOGGER.fine("updating postgis feature " + current);
098: }
099:
100: PreparedStatement statement = null;
101: Connection conn = null;
102:
103: try {
104: conn = queryData.getConnection();
105:
106: String sql = makeUpdateSql(live, current);
107: statement = conn.prepareStatement(sql);
108:
109: FeatureType schema = current.getFeatureType();
110: int position = 1;
111:
112: for (int i = 0; i < current.getNumberOfAttributes(); i++) {
113: AttributeType type = schema.getAttributeType(i);
114:
115: if (type instanceof GeometricAttributeType
116: && !DataUtilities.attributesEqual(current
117: .getAttribute(i), live.getAttribute(i))) {
118: Geometry geometry = (Geometry) current
119: .getAttribute(i);
120:
121: LOGGER
122: .fine("ORACLE SPATIAL: geometry to be written:"
123: + geometry);
124:
125: int srid = queryData.getFeatureTypeInfo().getSRID(
126: type.getName());
127: geometry.setSRID(srid);
128:
129: STRUCT struct = converter.toSDO(geometry);
130: statement.setObject(position, struct);
131: LOGGER
132: .fine("ORACLE SPATIAL: set geometry parameter at position:"
133: + position);
134: position++;
135:
136: break;
137: }
138: }
139:
140: // System.out.println(sql);
141: LOGGER.fine(sql);
142: statement.execute();
143: } catch (SQLException sqle) {
144: String msg = "SQL Exception writing geometry column"
145: + sqle.getLocalizedMessage();
146: LOGGER.log(Level.SEVERE, msg, sqle);
147: queryData.close(sqle);
148: throw new DataSourceException(msg, sqle);
149: } finally {
150: if (statement != null) {
151: try {
152: statement.close();
153: } catch (SQLException e) {
154: String msg = "Error closing JDBC Statement";
155: LOGGER.log(Level.WARNING, msg, e);
156: }
157: }
158: }
159: }
160:
161: /**
162: * Override that uses sql prepaired statements to perform the operation.
163: *
164: * @see org.geotools.data.jdbc.JDBCFeatureWriter#doInsert(org.geotools.data.jdbc.MutableFIDFeature)
165: */
166: protected void doInsert(MutableFIDFeature current)
167: throws IOException, SQLException {
168: LOGGER.fine("inserting into postgis feature " + current);
169:
170: PreparedStatement statement = null;
171: Connection conn = null;
172: try {
173: conn = queryData.getConnection();
174: String sql = makeInsertSql(current);
175: statement = conn.prepareStatement(sql);
176:
177: int position = 1;
178: FeatureType schema = current.getFeatureType();
179: for (int i = 0; i < current.getNumberOfAttributes(); i++) {
180: AttributeType type = schema.getAttributeType(i);
181: if (type instanceof GeometricAttributeType) {
182: Geometry geometry = (Geometry) current
183: .getAttribute(i);
184:
185: // set the proper SRID, otherwise insertion will fail due to issues
186: // with the spatial index
187: int srid = queryData.getFeatureTypeInfo().getSRID(
188: type.getName());
189: geometry.setSRID(srid);
190:
191: STRUCT struct = converter.toSDO(geometry);
192: statement.setObject(position, struct);
193: position++;
194: }
195: }
196: LOGGER.fine(sql);
197: statement.execute();
198:
199: // should the ID be generated during an insert, we need to read it back
200: // and set it into the feature
201: if (((mapper.getColumnCount() > 0) && mapper
202: .hasAutoIncrementColumns())) {
203: // if (((mapper.getColumnCount() > 0))) {
204: current
205: .setID(mapper
206: .createID(conn, current, statement));
207: }
208: } catch (SQLException sqle) {
209: String msg = "SQL Exception writing geometry column"
210: + sqle.getLocalizedMessage();
211: LOGGER.log(Level.SEVERE, msg, sqle);
212: queryData.close(sqle);
213: throw new DataSourceException(msg, sqle);
214: } finally {
215: if (statement != null) {
216: try {
217: statement.close();
218: } catch (SQLException e) {
219: String msg = "Error closing JDBC Statement";
220: LOGGER.log(Level.WARNING, msg, e);
221: }
222: }
223: }
224: }
225: }
|