2010-12-14 43 views
6

Trong thư viện giao tiếp cơ sở dữ liệu của tôi jOOQ, tôi muốn thêm hỗ trợ cho các gói Oracle (hoặc DB2, v.v.). Tôi đã thực hiện việc lưu trữ thủ tục/chức năng hỗ trợ mà mọi đối tượng được lưu trữ được mô hình hóa như một lớp Java được tạo ra. Ví dụ, chức năng lưu trữ nàyÁnh xạ giữa các gói Oracle và các gói Java

CREATE FUNCTION f_author_exists (author_name VARCHAR2) RETURNS NUMBER; 

sẽ tạo ra một lớp có thể được sử dụng như thế này (lưu ý, cũng có rất nhiều phương pháp thuận tiện, ví dụ này chỉ cho thấy thiết kế chung):

// 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(); 

Lý do tôi chọn một hàm SQL ánh xạ ->Java Class là vì các thủ tục được lưu trữ cho phép các giá trị trả về phức tạp (một số tham số OUT hoặc OUT OUT) mà tôi muốn có thể lấy từng cái một sau khi gọi thủ tục:

p.getOutParam1(); 
p.getOutParam2(); 

Thiết kế này hoạt động tốt với các chức năng/thủ tục được lưu trữ, nơi không thể quá tải quá tải. Trong gói của Oracle (hoặc DB2 của), tuy nhiên, tôi có thể có một số chức năng có cùng tên, như

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; 

Khi tôi tạo ra một lớp cho mỗi chức năng (hoặc thủ tục), tôi sẽ có cuộc đụng độ đặt tên với một số FAuthorExists lớp Java . Giải pháp lame là thêm chỉ mục vào tên lớp, chẳng hạn như FAuthorExists2, FAuthorExists3. Một giải pháp lame khác là tạo ra một số giá trị băm (hoặc bản thân giá trị) từ các tên/kiểu tham số trực tiếp vào tên lớp, chẳng hạn như FAuthorExistsVARCHAR2, FAuthorExistsVARCHAR2VARCHAR2. Không giải pháp nào là mong muốn vì lý do rõ ràng.

Có ai có giải pháp đơn giản cho vấn đề này không? Hoặc có lẽ một ý tưởng về một thiết kế tổng thể tốt hơn mà sẽ không tạo ra các vấn đề quá tải tên chức năng như vậy?

Bất kỳ phản hồi nào được đánh giá cao!

Trả lời

0

Tôi thấy không có cách nào khả thi khác để giải quyết vấn đề này hơn là sử dụng "chỉ số quá tải" trên các lớp được tạo ra. Do đó, gói

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; 

Sẽ tạo ra các lớp:

public class FAuthorExists1 { /* ... */ } 
public class FAuthorExists2 { /* ... */ } 

ý tưởng khác sẽ chỉ gây ra xung đột mới tại thời điểm mã thế hệ, hoặc khi chạy.

CẬP NHẬT: Lưu ý, giải pháp này cũng dường như là người duy nhất để xử lý tình huống như thế này một cách chính xác:

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; 

Như có vẻ như, loại này quá tải là có thể trong PL/SQL, quá.

3

getReturnValue Chức năng của bạn có thể xác định vào thời điểm cuộc gọi mà quá tải chức năng gọi tùy thuộc vào có bao nhiêu thông số đầu vào đã được thiết lập - nhưng tôi nghĩ rằng nó sẽ kết thúc được đơn giản hơn nếu bạn dính vào một cái gì đó giống như setParam1 hơn setName

+0

Phương thức 'execute()' thực hiện cuộc gọi thực tế. Phương thức này được gọi là 'setName()' vì đối số hàm 'name'. Tôi đã sửa nó trong ví dụ, để làm cho nó rõ ràng hơn. Ý tưởng của bạn không phải là một ý tưởng tồi. Mặc dù, vấn đề là nếu bạn có quá tải tên hàm với các bộ đối số rất riêng biệt, thì nó có thể trở nên khó hiểu để tìm ra, kết hợp các đối số nào là có thể. Nhưng với các phương pháp tiện lợi, điều đó có thể thực sự hiệu quả! 1 cho ý tưởng xác định cuộc gọi chính xác tại thời gian chạy –

+0

@Lukas khớp với các loại đối số thay vì tên là ý tôi muốn nói - tôi nghĩ nó có thể đơn giản hơn. Dù vậy, tôi nghĩ có thể là nguyên tắc có thể. –

+0

Thật dễ dàng để tìm thấy một thực hiện tốt về cách gọi hàm dựa trên tên/loại/vị trí đối số. Nhưng phần khó khăn là làm cho mã được tạo dễ sử dụng cho các nhà phát triển. Đó là lý do tại sao tôi sử dụng tên của đối số trong các phương thức đã tạo –

0

Bạn có thể khắc phục các hạn chế của quá tải bằng cách đặt tên duy nhất cho từng chức năng.Điều này cũng sẽ cải thiện khả năng đọc của mã (đó là một lý do why Golang doesn't have overloading). Ví dụ: f_author_name_exists, f_author_name_country_exists.

Một cách khác, sẽ làm phức tạp các lớp Java, là quyết định thời gian chạy mà thủ tục cần gọi, dựa trên đó quá trình xây dựng Java đã được sử dụng hoặc setters đã được sử dụng.

+0

Cảm ơn các gợi ý của bạn. Như đã nêu trong câu hỏi, đây là về [jOOQ] (http://www.jooq.org), một tiện ích tạo mã nguồn cho các thủ tục được lưu trữ, vì vậy tôi không có quyền kiểm soát quá tải tên thủ tục - mà tôi không ' t tâm trí ở tất cả. Nó thêm vào tính biểu cảm của một API khi tạo các phương thức tiện lợi. Mặt khác, do sự hiện diện của các tham số 'OUT', rất khó để quyết định thủ tục nào cần gọi khi chạy, nếu cuộc gọi đó không có dây cứng tại thời gian tạo mã ... –

Các vấn đề liên quan