Сопоставление пакетов Oracle и пакетов Java
в моей библиотеке интерфейсов базы данных jOOQ, Я хотел бы добавить поддержку пакетов Oracle (или DB2 и т. д.). Я уже реализовал поддержку хранимых процедур / функций, где каждый хранимый объект моделируется как сгенерированный класс Java. Например, эта хранимая функция
CREATE FUNCTION f_author_exists (author_name VARCHAR2) RETURNS NUMBER;
будет генерировать класс, который можно использовать следующим образом (обратите внимание, есть также много методов удобства, этот пример просто показывает общий дизайн):
// 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();
в причина, по которой я выбрал отображение функции SQL ->Java-Класс это потому, что хранимые процедуры позволяют сложные возвращаемые значения( несколько параметров OUT или IN OUT), которые я хочу иметь возможность получать по одному после вызова процедуры:
p.getOutParam1();
p.getOutParam2();
теперь этот дизайн отлично работает с сохраненными функциями / процедурами, где перегрузка не возможно. Однако в пакетах Oracle (или DB2) у меня может быть несколько функций с одинаковым именем, как
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;
когда я создаю класс для каждой функции (или процедуры), у меня будут столкновения имен с несколькими FAuthorExists
Java-классов. Хромым решением является добавление индекса к имени класса, например FAuthorExists2
, FAuthorExists3
. Другим хромым решением является создание некоторого хэш-значения (или самого значения) из имен параметров/типов непосредственно в classname, например FAuthorExistsVARCHAR2
, FAuthorExistsVARCHAR2VARCHAR2
. Ни одно из решений не является желательным по очевидным причинам.
у кого-нибудь есть простой решение этой проблемы? Или, может быть, идея лучшего общего дизайна, который не будет создавать такие проблемы перегрузки имени функции?
любая обратная связь ценится!
3 ответов
код getReturnValue
функция может определить во время вызова, какая перегруженная функция для вызова в зависимости от того, сколько входных параметров было установлено - но я думаю, что это будет проще, если вы придерживаетесь чего-то вроде setParam1
, а не setName
Я не нашел другого жизнеспособного способа решить эту проблему, чем использовать "индекс перегрузки" для сгенерированных классов. Следовательно, пакет
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;
произведет эти классы:
public class FAuthorExists1 { /* ... */ }
public class FAuthorExists2 { /* ... */ }
другие идеи просто вызовут новые конфликты во время генерации кода или во время выполнения.
обновление: обратите внимание, что это решение также кажется единственным, чтобы правильно обрабатывать такие ситуации:
CREATE PACKAGE my_package IS
PROCEDURE f_author_exists (name VARCHAR2);
PROCEDURE f_author_exists (name CHAR);
PROCEDURE f_author_exists (name CHAR, country OUT VARCHAR2);
END my_package;
как кажется, это своего рода перегрузка возможно и в PL / SQL тоже.
вы можете преодолеть ограничения перегрузки, давая уникальные имена для каждой функции. Это также улучшило бы читаемость кода (это одна из причин почему Golang не имеет перегрузки). Например, f_author_name_exists, f_author_name_country_exists.
другой способ, который усложнит классы Java, - решить во время выполнения, какую процедуру вызывать, на основе которой использовался перегруженный конструктор Java или какие сеттеры были используемый.