Картирование между пакетами Oracle и Java Packages
-
09-10-2019 - |
Вопрос
В моей базе данных библиотеки взаимодействия Джук, Я хотел бы добавить поддержку пакетов 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 Class является потому, что сохраненные процедуры разрешают сложные возвратные значения (несколько Out или в параметрах 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
. Анкет Другое хромое решение - генерировать какое -то значение хэша (или самое значение) из имен/типов параметров непосредственно в имя класса, например, как FAuthorExistsVARCHAR2
, FAuthorExistsVARCHAR2VARCHAR2
. Анкет Ни одно решение не желательно по понятным причинам.
У кого -нибудь есть простое решение этой проблемы? Или, может быть, идея лучшего общего дизайна, который не создаст таких проблем с перегрузкой и названием функции?
Любая обратная связь оценила!
Решение 2
Я не нашел никакого другого жизнеспособного способа решения этой проблемы, чем использование «индекса перегрузки» в сгенерированных классах. Следовательно, пакет
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.
Другие советы
Ваш getReturnValue
Функция может определить во время вызовов, какую перегруженную функцию вызовы в зависимости от того, сколько входных параметров было установлено - но я думаю, что в конечном итоге будет проще, если вы придерживаетесь чего -то подобного setParam1
скорее, чем setName
Вы можете преодолеть ограничения перегрузки, предоставив уникальные имена для каждой функции. Это также улучшит читаемость кода (это одна из причин Почему у Голанга нет перегрузки) Например, f_author_name_exists, f_author_name_country_exists.
Другой способ, который усложнит классы Java, - решить во время выполнения то, какую процедуру вызывает, в зависимости от того, какой перегруженный конструктор Java был использован или какие сеттеры использовались.