1 56 57 package org.objectstyle.cayenne.dba.oracle; 58 59 import java.lang.reflect.Field ; 60 import java.lang.reflect.Method ; 61 import java.sql.Connection ; 62 import java.sql.PreparedStatement ; 63 import java.sql.SQLException ; 64 import java.sql.Types ; 65 66 import org.apache.log4j.Logger; 67 import org.objectstyle.cayenne.CayenneRuntimeException; 68 import org.objectstyle.cayenne.access.DataNode; 69 import org.objectstyle.cayenne.access.OperationObserver; 70 import org.objectstyle.cayenne.access.trans.QualifierTranslator; 71 import org.objectstyle.cayenne.access.trans.QueryAssembler; 72 import org.objectstyle.cayenne.access.trans.TrimmingQualifierTranslator; 73 import org.objectstyle.cayenne.access.types.ByteArrayType; 74 import org.objectstyle.cayenne.access.types.ByteType; 75 import org.objectstyle.cayenne.access.types.CharType; 76 import org.objectstyle.cayenne.access.types.DefaultType; 77 import org.objectstyle.cayenne.access.types.ExtendedTypeMap; 78 import org.objectstyle.cayenne.access.types.ShortType; 79 import org.objectstyle.cayenne.access.util.BatchQueryUtils; 80 import org.objectstyle.cayenne.dba.JdbcAdapter; 81 import org.objectstyle.cayenne.dba.PkGenerator; 82 import org.objectstyle.cayenne.map.DbAttribute; 83 import org.objectstyle.cayenne.map.DbEntity; 84 import org.objectstyle.cayenne.query.BatchQuery; 85 import org.objectstyle.cayenne.query.Query; 86 import org.objectstyle.cayenne.query.SQLAction; 87 import org.objectstyle.cayenne.query.SelectQuery; 88 import org.objectstyle.cayenne.util.Util; 89 90 109 public class OracleAdapter extends JdbcAdapter { 110 111 private static Logger logObj = Logger.getLogger(OracleAdapter.class); 112 113 public static final String ORACLE_FLOAT = "FLOAT"; 114 public static final String ORACLE_BLOB = "BLOB"; 115 public static final String ORACLE_CLOB = "CLOB"; 116 117 public static final String TRIM_FUNCTION = "RTRIM"; 118 public static final String NEW_CLOB_FUNCTION = "EMPTY_CLOB()"; 119 public static final String NEW_BLOB_FUNCTION = "EMPTY_BLOB()"; 120 121 protected static boolean initDone; 122 protected static int oracleCursorType = Integer.MAX_VALUE; 123 protected static Method outputStreamFromBlobMethod; 124 protected static Method writerFromClobMethod; 125 protected static boolean supportsOracleLOB; 126 127 static { 128 initDriverInformation(); 132 } 133 134 protected static void initDriverInformation() { 135 initDone = true; 136 137 try { 139 Class oraTypes = Class.forName("oracle.jdbc.driver.OracleTypes"); 140 Field cursorField = oraTypes.getField("CURSOR"); 141 oracleCursorType = cursorField.getInt(null); 142 143 outputStreamFromBlobMethod = Class 144 .forName("oracle.sql.BLOB") 145 .getMethod("getBinaryOutputStream", new Class [0]); 146 147 writerFromClobMethod = Class 148 .forName("oracle.sql.CLOB") 149 .getMethod("getCharacterOutputStream", new Class [0]); 150 supportsOracleLOB = true; 151 152 } 153 catch (Throwable th) { 154 logObj.info("Error getting Oracle driver information, ignoring. " 155 + "Note that certain adapter features will be disabled.", Util 156 .unwindException(th)); 157 } 158 } 159 160 public static Method getOutputStreamFromBlobMethod() { 161 return outputStreamFromBlobMethod; 162 } 163 164 public static boolean isSupportsOracleLOB() { 166 return supportsOracleLOB; 167 } 168 169 public static Method getWriterFromClobMethod() { 170 return writerFromClobMethod; 171 } 172 173 180 public static int getOracleCursorType() { 181 182 if (oracleCursorType == Integer.MAX_VALUE) { 183 throw new CayenneRuntimeException( 184 "No information exists about oracle types. " 185 + "Check that Oracle JDBC driver is available to the application."); 186 } 187 188 return oracleCursorType; 189 } 190 191 public OracleAdapter() { 192 setSupportsBatchUpdates(true); 194 } 195 196 200 protected void configureExtendedTypes(ExtendedTypeMap map) { 201 super.configureExtendedTypes(map); 202 203 map.registerType(new CharType(true, true)); 205 206 map.registerType(new ByteArrayType(true, true)); 208 209 map.registerType(new OracleUtilDateType()); 211 212 map.registerType(new ShortType(true)); 214 map.registerType(new ByteType(true)); 215 216 map.registerType(new OracleIntegerType()); 222 map.registerType(new OracleDoubleType()); 223 } 224 225 229 protected PkGenerator createPkGenerator() { 230 return new OraclePkGenerator(); 231 } 232 233 237 public String dropTable(DbEntity ent) { 238 return "DROP TABLE " + ent.getFullyQualifiedName() + " CASCADE CONSTRAINTS"; 239 } 240 241 245 public DbAttribute buildAttribute( 246 String name, 247 String typeName, 248 int type, 249 int size, 250 int precision, 251 boolean allowNulls) { 252 253 DbAttribute attr = super.buildAttribute(name, 254 typeName, 255 type, 256 size, 257 precision, 258 allowNulls); 259 260 if (type == Types.DECIMAL && precision <= 0) { 261 attr.setType(Types.INTEGER); 262 attr.setPrecision(-1); 263 } 264 else if (type == Types.OTHER) { 265 if (ORACLE_FLOAT.equals(typeName)) { 268 attr.setType(Types.FLOAT); 269 } 270 else if (ORACLE_BLOB.equals(typeName)) { 271 attr.setType(Types.BLOB); 272 } 273 else if (ORACLE_CLOB.equals(typeName)) { 274 attr.setType(Types.CLOB); 275 } 276 } 277 278 return attr; 279 } 280 281 286 protected Class queryTranslatorClass(Query q) { 287 if (q instanceof SelectQuery) { 288 return OracleSelectTranslator.class; 289 } 290 else { 291 return super.queryTranslatorClass(q); 292 } 293 } 294 295 298 public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) { 299 return new TrimmingQualifierTranslator( 300 queryAssembler, 301 OracleAdapter.TRIM_FUNCTION); 302 } 303 304 309 public SQLAction getAction(Query query, DataNode node) { 310 return query.createSQLAction(new OracleActionBuilder(this, node.getEntityResolver())); 311 } 312 313 318 public boolean shouldRunBatchQuery( 319 DataNode node, 320 Connection con, 321 BatchQuery query, 322 OperationObserver delegate) throws SQLException , Exception { 323 324 if (isSupportsOracleLOB() 326 && BatchQueryUtils.updatesLOBColumns(query) 327 && (node instanceof OracleDataNode)) { 328 329 OracleDataNode oracleNode = (OracleDataNode) node; 330 oracleNode.runBatchUpdateWithLOBColumns(con, query, delegate); 331 332 return false; 333 } 334 else { 335 return super.shouldRunBatchQuery(node, con, query, delegate); 336 } 337 } 338 339 342 final class OracleIntegerType extends DefaultType { 343 344 public OracleIntegerType() { 345 super(Integer .class.getName()); 346 } 347 348 public void setJdbcObject( 349 PreparedStatement st, 350 Object val, 351 int pos, 352 int type, 353 int precision) throws Exception { 354 355 if (val != null) { 356 st.setInt(pos, ((Number ) val).intValue()); 357 } 358 else { 359 super.setJdbcObject(st, val, pos, type, precision); 360 } 361 } 362 } 363 364 367 final class OracleDoubleType extends DefaultType { 368 369 public OracleDoubleType() { 370 super(Double .class.getName()); 371 } 372 373 public void setJdbcObject( 374 PreparedStatement st, 375 Object val, 376 int pos, 377 int type, 378 int precision) throws Exception { 379 380 if (val != null) { 381 st.setDouble(pos, ((Number ) val).doubleValue()); 382 } 383 else { 384 super.setJdbcObject(st, val, pos, type, precision); 385 } 386 } 387 } 388 } | Popular Tags |