In meiner Datenbank Interface-Bibliothek jOOQ möchte ich Unterstützung für Oracle (oder DB2, usw.) Pakete hinzufügen. Ich habe bereits eine Unterstützung für gespeicherte Prozeduren/Funktionen implementiert, wobei jedes gespeicherte Objekt als generierte Java-Klasse modelliert wird. Zum Beispiel diese gespeicherte FunktionMapping zwischen Oracle-Paketen und Java-Paketen
CREATE FUNCTION f_author_exists (author_name VARCHAR2) RETURNS NUMBER;
wird eine Klasse erzeugen, wie diese verwendet werden können (beachten Sie, gibt es auch viele bequeme Methoden, dieses Beispiel zeigt nur das allgemeine Design):
// 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();
Der Grund, warum ich eine Zuordnung SQL-Funktion ->Java-Klasse wählte, ist, weil gespeicherte Prozeduren komplexe Rückgabewerte (mehrere OUT- oder IN OUT-Parameter) ermöglichen, die ich nach dem Aufruf der Prozedur nacheinander abrufen kann:
p.getOutParam1();
p.getOutParam2();
Jetzt funktioniert dieses Design gut mit gespeicherten Funktionen/Prozeduren, wobei überladen nicht möglich ist. Innerhalb von Oracle (oder DB2 ist) Pakete jedoch kann ich mehrere Funktionen mit dem gleichen Namen, wie
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;
Wenn ich eine Klasse pro Funktion (oder Prozedur) erzeugen, werde ich Namensgebung Auseinandersetzungen mit mehreren FAuthorExists
Java Klassen . Eine lahme Lösung besteht darin, dem Klassennamen einen Index hinzuzufügen, z. B. FAuthorExists2
, FAuthorExists3
. Eine andere lahme Lösung besteht darin, eine Art Hash-Wert (oder den Wert selbst) aus den Parameternamen/-typen direkt in den Klassennamen zu erzeugen, wie z. B. FAuthorExistsVARCHAR2
, FAuthorExistsVARCHAR2VARCHAR2
. Keine der beiden Lösungen ist aus offensichtlichen Gründen wünschenswert.
Hat jemand eine einfache Lösung für dieses Problem? Oder vielleicht eine Idee eines besseren Gesamtdesigns, das keine Probleme mit dem Überladen von Funktionsnamen erzeugen würde?
Jedes Feedback geschätzt!
Die 'execute()' Methode macht den eigentlichen Aufruf. Die Methode heißt wegen des Funktionsarguments 'name'' setName() '. Ich habe das im Beispiel behoben, um es klarer zu machen. Deine Idee ist nicht schlecht. Obwohl das Problem darin besteht, dass Funktionsnamen mit sehr unterschiedlichen Argumentgruppen überladen werden, kann es verwirrend sein, herauszufinden, welche Kombination von Argumenten möglich ist. Aber mit den Convenience-Methoden könnte das tatsächlich funktionieren! +1 für die Idee, den richtigen Aufruf zur Laufzeit zu bestimmen –
@Lukas passend zu Argumenttypen statt Namen war was ich mit meinem Vorschlag meinte - ich dachte, es könnte einfacher sein. Ich denke, dass beides prinzipiell möglich wäre. –
Es ist einfach, eine gute Implementierung zu finden, wie man die Funktion basierend auf Argumentnamen/types/position aufruft. Aber der schwierige Teil besteht darin, den generierten Code für Entwickler einfach zu verwenden. Deshalb verwende ich den Namen des Arguments in den generierten Methoden –