Отображение между пакетами Oracle и пакетами Java - PullRequest
6 голосов
/ 14 декабря 2010

В моей библиотеке интерфейса базы данных 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.Другое неудачное решение состоит в том, чтобы сгенерировать какое-либо хэш-значение (или само значение) из имен / типов параметров непосредственно в имя класса, например FAuthorExistsVARCHAR2, FAuthorExistsVARCHAR2VARCHAR2.Ни одно из решений не желательно по очевидным причинам.

У кого-нибудь есть простое решение этой проблемы?Или, может быть, идея лучшего общего дизайна, который не вызвал бы таких проблем с перегрузкой имен функций?

Любые отзывы приветствуются!

Ответы [ 3 ]

3 голосов
/ 14 декабря 2010

Ваша функция getReturnValue может определить во время вызова, какую перегруженную функцию вызывать, в зависимости от того, сколько входных параметров было установлено - но я думаю, что в итоге будет проще, если вы будете придерживаться чего-то вроде setParam1 вместо setName

0 голосов
/ 11 мая 2012

Вы можете преодолеть ограничения перегрузки, задав уникальные имена для каждой функции.Это также улучшит читабельность кода (это одна из причин , почему у Golang нет перегрузки ).Например, f_author_name_exists, f_author_name_country_exists.

Другой способ, который усложнит классы Java, - это решить во время выполнения, какую процедуру вызывать, основываясь на том, какой перегруженный конструктор Java использовался или какие установщики использовались.

0 голосов
/ 20 декабря 2010

Я не нашел другого жизнеспособного способа решения этой проблемы, кроме использования «индекса перегрузки» в сгенерированных классах.Следовательно, пакет

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.

...