2010-12-14 9 views
6

私のデータベース・インタフェース・ライブラリjOOQでは、Oracle(またはDB2など)パッケージのサポートを追加したいと考えています。私はすでにストアド・プロシージャ/関数のサポートを実装しています。ここでは、ストアド・オブジェクトはすべて、生成されたJavaクラスとしてモデル化されています。例えば、この記憶された関数Oracleパッケージと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クラスストアドプロシージャは、プロシージャをコールした後に1つずつフェッチできるようにする複雑な戻り値(複数の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のようなクラス名にインデックスを追加することです。もう一つの難解な解決策は、パラメータ名/型からある種のハッシュ値(または値そのもの)をFAuthorExistsVARCHAR2FAuthorExistsVARCHAR2VARCHAR2などのクラス名に直接生成することです。明らかな理由から、いずれの解決策も望ましくない。

誰にもこの問題の簡単な解決策がありますか?このような関数名のオーバーロードの問題を引き起こさない、より優れた全体的なデザインのアイデアですか?

フィードバックが高く評価されました。

答えて

0

ような何かに固執するならば、それは単純になってしまうだろうと思います生成されたクラスで「オーバーロードインデックス」を使用するよりも、この問題を解決する他の実行可能な方法は見つかりませんでした。したがって、パッケージ

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 { /* ... */ } 

他のアイデアは、単にコード生成時に、新たな紛争を引き起こし、または実行時になります。

UPDATE:注意、このソリューションは、正しくこのような状況に対処する唯一のようだ:

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で可能です。

3

あなたgetReturnValue関数は、パラメータが設定されているどのように多くの入力に応じて呼び出す関数をオーバーロードされたコールの時点で決定することができる - 私はあなたがsetParam1はなくsetName

+0

'実行() 'メソッドは、実際の呼び出しを行います。このメソッドは、関数の引数 'name'のために' setName() 'と呼ばれます。この例では、それをもっと明確にするように修正しました。あなたのアイデアは悪いものではありません。けれども、問題は非常に明確な引数セットでのオーバーロード関数名を持っている場合、それは可能である引数のどのような組み合わせで、見つけることが混乱になるかもしれないです。しかし、便利な方法では、実際に動作するかもしれません!引数の型ではなく名前で、実行時に –

+0

@Lukasマッチングを正しいコールを決定するという考えのための+1は、私は私の提案によって意味したものだった - 私はそれが簡単になるかもしれないと思いました。私はどちらかというと原理的には可能だと思う。 –

+0

引数の名前/種類/位置に基づいて関数を呼び出す方法についての良い実装を簡単に見つけることができます。しかし、難しいのは、生成されたコードを開発者に使いやすくすることです。だからこそ、私は生成されたメソッドで引数の名前を使用します –

0

各機能に固有の名前を付けることで、オーバーロードの制限を克服することができます。これにより、コードの可読性も向上します(その理由の1つはwhy Golang doesn't have overloadingです)。たとえば、f_author_name_exists、f_author_name_country_existsなどです。 Javaクラスが複雑になります

もう一つの方法は、Javaのコンストラクタが使用されたか、セッターが使用されたオーバーロードされた手順は、それに基づいて、呼び出すために、実行時に決定することです。

+0

あなたのヒントをありがとう。この質問に記載されているように、これはストアドプロシージャのソースコードを生成するユーティリティである[jOOQ](http://www.jooq.org)に関するものなので、プロシージャ名のオーバーロードを制御することはできません。まったく気にしない。これは、便利なメソッドを作成する際のAPIの表現力を高めます。一方、 'OUT'パラメータがあるため、コード生成時にその呼び出しがハードワイヤリングされていない場合、実行時にどのプロシージャを呼び出すかを決めることは難しいです... –

関連する問題