JDBC Metadaten für Oracle stored procedures

5. April 2010 von Jan Lolling in Java, Java Code Beispiele
Schlagwörter:

Das Konstrukt der Packages wird durch JDBC nicht wirklich gut unterstützt. JDBC geht leider auch von eindeutigen Namen für functions und procedures aus. Somit hat man ein Problem mit überladenen procedures. Diese unterscheiden sich nicht im Namen sondern in der Anzahl und Typen der Parameter.
Der Oracle-JDBC-Treiber gibt alle Informationen raus, es erfordert nur etwas Geschick diese Informationen einzusammeln.
1. Die Name der packages werden als CATALOG ausgegeben.
2. Die Parameter kennen ihren Index. Wenn ein Parameter für scheinbar die selbe procedure erscheint mit dem gleichen Index, dann ist das ein Zeichen für eine überladene procedure.

Der folgende Beispielcode geht davon aus, dass die procedures und functions in speziellen Objekten gehalten werden und die Parameter besitzen auch ihre eigene Transferklasse.

	/**
	 * load procedure and functions
	 * 
	 * @param schema
	 *            object that represent a schema
	 * @return true if everything went well
	 */
	public boolean loadProcedures(SQLSchema schema) {
		if (logger.isDebugEnabled()) {
			logger.debug("loadProcedures schema=" + schema);
		}
		// makes this thread save
		inRefreshCycle = true;
		boolean ok = false;
		// don' worry about that, we use our own database pool
		final DatabaseSession session = DatabaseSessionPool.getDatabaseSession(cd.getUniqueId());
		if (session == null) {
			// return if no connection to database avialable
			return false;
		}
		try {
			Connection conn = session.getConnection();
			DatabaseMetaData dbmd = conn.getMetaData();
			schema.clearProcedures(); // remove any previously loaded procedures
			ResultSet rs = dbmd.getProcedures(null, schema.getName(), null);
			if (rs != null) {
				// loading all procedures and functions
				while (rs.next()) {
					// PROCEDURE_CAT contains the package name
					String catalogName = rs.getString("PROCEDURE_CAT");
					String name = rs.getString("PROCEDURE_NAME");
					if (catalogName != null && catalogName.length() > 0) {
						name = catalogName + "." + name;
					}
					// create an new one
					SQLProcedure procedure = new SQLProcedure(this, schema,	name);
					// decide if it is a function
					short pType = rs.getShort("PROCEDURE_TYPE");
					procedure.setFunction(pType == DatabaseMetaData.procedureReturnsResult);
					schema.addProcedure(procedure);
					objectMap.put(name, procedure);
				}
				rs.close();
			}
			// loading procedure/function parameters
			rs = dbmd.getProcedureColumns(null, schema.getName(), null, null);
			if (rs != null) {
				// an index for overloaded procedures
				int procedureIndex = 0;
				String prevProcedureName = "noprocedurehere_xx";
				while (rs.next()) {
					// PROCEDURE_CAT contains the package name
					String catalogName = rs.getString("PROCEDURE_CAT");
					String name = rs.getString("PROCEDURE_NAME");
					if (catalogName != null && catalogName.length() > 0) {
						// add the catalog name as package name
						name = catalogName + "." + name;
					}
					int pos = 0;
					try {
						// position of this parameter in the procedure parameter
						// list
						pos = rs.getInt("ORDINAL_POSITION");
					} catch (Exception e) {
						// perhaps this column is not defined in every database
						// type
						pos = -1;
					}
					if (prevProcedureName.equals(name)) {
						if (pos == 0) {
							// if we get the same procedure name and a parameter
							// with position zero increase the procedure index
							// that means point to the next procedure with the
							// same name
							procedureIndex++;
						}
					} else {
						procedureIndex = 0;
					}
					String columnName = rs.getString("COLUMN_NAME");
					List list = schema.getProcedures(name);
					SQLProcedure procedure = list.get(procedureIndex);
					if (procedure != null) {
						procedure.addParameter(columnName, // parameter name
								rs.getShort("DATA_TYPE"),  // parameter type as
														   // integer defined
														   // in class
														   // java.sql.Type
								rs.getString("TYPE_NAME"), // parameter type as
														   // string
								rs.getInt("LENGTH"),    // length of the parameter
														// if parameter is
														// string or number type
								rs.getInt("PRECISION"), // precision of the
														// parameter if the
														// parameter is a number
														// type
								rs.getShort("COLUMN_TYPE")); // input or output
														     // parameter as
														     // integer:
															 // refer
															 // DatabaseMetaData.procedureColumnReturn
					}
					// keep the name of the last procedure to detect overloaded
					// procedures
					prevProcedureName = name;
				}
				rs.close();
			}
			schema.setProcedureLoaded();
			ok = true;
		} catch (SQLException sqle) {
			// creates a error message to show it in GUI
			errorMessage = "loadProcedures schema=" + schema + " failed: "
					+ sqle.getMessage();
		} finally {
			// put the session back in the pool
			DatabaseSessionPool.release(session);
		}
		inRefreshCycle = false;
		return ok;
	}
  • Kommentare deaktiviert