En mi biblioteca de interfaces de bases de datos jOOQ, me gustaría agregar soporte para paquetes Oracle (o DB2, etc.). Ya he implementado el procedimiento almacenado/soporte de funciones donde cada objeto almacenado se modela como una clase Java generada. Por ejemplo, esta función almacenadaAsignación entre paquetes Oracle y paquetes Java
CREATE FUNCTION f_author_exists (author_name VARCHAR2) RETURNS NUMBER;
generará una clase que puede ser utilizado como esto (nota, también hay un montón de métodos de conveniencia, este ejemplo demuestra el diseño general):
// A new "function call instance". The function needs to be instanciated
// once per call
FAuthorExists f = new FAuthorExists();
// Set the function parameters on the call instance and call it
f.setAuthorName("Paulo");
f.execute(connection);
// Fetch the result from the function call instance
BigDecimal result = f.getReturnValue();
El motivo por el que elegí una función de SQL ->Java Class es porque los procedimientos almacenados permiten valores de retorno complejos (varios parámetros OUT o IN OUT) que deseo poder buscar uno por uno después de llamar al procedimiento:
p.getOutParam1();
p.getOutParam2();
Ahora este diseño funciona bien con funciones/procedimientos almacenados, donde sobrecarga no es posible. Dentro de los paquetes de Oracle (o DB2 de), sin embargo, puedo tener varias funciones con el mismo nombre, como
CREATE PACKAGE my_package IS
FUNCTION f_author_exists (name VARCHAR2) RETURNS NUMBER;
FUNCTION f_author_exists (name VARCHAR2, country VARCHAR2) RETURNS NUMBER;
END my_package;
Cuando genero una clase por cada función (o procedimiento), que tendrá choques de nombres con varios FAuthorExists
clases Java . Una solución incorrecta es agregar un índice al nombre de la clase, como FAuthorExists2
, FAuthorExists3
. Otra solución coja es generar algún tipo de valor hash (o el valor mismo) de los nombres/tipos de parámetros directamente en el nombre de clase, como FAuthorExistsVARCHAR2
, FAuthorExistsVARCHAR2VARCHAR2
. Ninguna de las soluciones es deseable por razones obvias.
¿Alguien tiene una solución simple a este problema? ¿O tal vez una idea de un mejor diseño general que no produciría problemas de sobrecarga de nombre de función?
¡Cualquier comentario apreciado!
El método 'execute()' realiza la llamada real. El método se llama 'setName()' debido al argumento de la función 'name'. Lo arreglé en el ejemplo, para hacerlo más claro. Tu idea no es mala. Aunque, el problema es si tiene una sobrecarga de nombre de función con conjuntos de argumentos muy distintos, entonces puede ser confuso descubrir qué combinación de argumentos es posible. ¡Pero con los métodos de conveniencia, eso realmente podría funcionar! +1 para la idea de determinar la llamada correcta en tiempo de ejecución –
@Lukas coincidir en tipos de argumento en lugar de nombres fue lo que quise decir con mi sugerencia, pensé que podría ser más simple. Creo que cualquiera de los dos sería posible en principio. –
Es fácil encontrar una buena implementación sobre cómo llamar a la función en función de los nombres/tipos/posición de los argumentos. Pero la parte difícil es hacer que el código generado sea fácil de usar para los desarrolladores. Es por eso que uso el nombre del argumento en los métodos generados –