2012-10-31 54 views
12

Tôi đang gặp sự cố khi gọi hàm FUNCTION của Oracle (không phải là Thủ tục được lưu trữ) từ Java 1.6, sử dụng ojdbc14.jar.Gọi hàm Oracle từ Java

Tôi không biết những gì hàm chứa như tôi gọi nó từ một máy chủ từ xa, tất cả tôi biết là thế này:

FUNCTION ap_ch_get_acct_balances (VAR_PI_MOB_NO_ACCT_NO VARCHAR2, 
VAR_REPLY_CODE OUT NUMBER, VAR_EXT_RESPONSE OUT VARCHAR2, VAR_PO_ACC_BAL OUT CHAR, 
VAR_PO_ACCT_NO OUT CHAR) 

Giản đồ tôi cần phải sử dụng là: FCRLIVE.AP_CH_GET_ACCT_BALANCES

tôi đang cố gắng này:

String call = "{ ? = call FCRLIVE.AP_CH_GET_ACCT_BALANCES(?, ?, ?, ?, ?) }"; 
         CallableStatement cstmt = conn.prepareCall(call); 
         cstmt.setQueryTimeout(1800); 
         cstmt.setString(1, inputCode); 
         cstmt.registerOutParameter(2, oracle.jdbc.OracleTypes.NUMBER); 
         cstmt.registerOutParameter(3, oracle.jdbc.OracleTypes.VARCHAR); 
         cstmt.registerOutParameter(4, oracle.jdbc.OracleTypes.CHAR); 
         cstmt.registerOutParameter(5, oracle.jdbc.OracleTypes.CHAR); 
         cstmt.executeUpdate(); 

Nhưng tôi cứ nhìn thấy điều này trong file log:

java.sql.SQLException: ORA-01006: bind variable does not exist 
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134) 
    at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:289) 
    at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:573) 
    at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1891) 
    at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteFetch(TTC7Protocol.java:1093) 
    at oracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:2047) 
    at oracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:1940) 
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2688) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:589) 

Tôi có gọi chức năng sai không? Hoặc điều này có thể là gì?

Cảm ơn bạn đã trợ giúp!

+0

loại trả về của 'ap_ch_get_acct_balances' là gì? – user1516873

+0

Nó trả về 4 tham số. 3 số nguyên và 1 chuỗi – lulu88

+1

Chức năng của bạn sẽ trả về một cái gì đó. 'FUNCTION ap_ch_get_acct_balances (định nghĩa tham số vào và ra ...) trả về NUMBER' chẳng hạn. Vì vậy, những gì chức năng của bạn trở lại loại? – user1516873

Trả lời

10

nó nên là:

String call = "{ ? = call FCRLIVE.AP_CH_GET_ACCT_BALANCES(?, ?, ?, ?, ?) }"; 
+0

Cảm ơn bạn đã phản hồi nhanh! Tôi đã thử rằng, sau đó tôi nhận: java.sql.SQLException: ORA-01008: không phải tất cả các biến bị ràng buộc – lulu88

+0

đó là vì bạn đặt ràng buộc chỉ 5 thông số, và bạn có 6 trong hàm Oracle: trả về param + 5 trong định nghĩa. Ngoài ra bạn đã gõ sai. Chỉ các tham số OUT phải được thêm vào bởi tham số "registerOutParameter" và IN (đầu tiên trong khai báo hàm), như "setParameter ..."). Hãy cẩn thận về thứ tự và chỉ mục của chúng :) – konradkg

+0

Tôi đã thấy điều đó! Bây giờ tôi đã thay đổi mã - chỉnh sửa ở trên .. – lulu88

0

Bạn cần phải xác định tham số trả về bởi hàm:

String call = "{ ? = call FCRLIVE.AP_CH_GET_ACCT_BALANCES(?, ?, ?, ?, ?) }"; 
        CallableStatement cstmt = conn.prepareCall(call); 
        cstmt.setQueryTimeout(1800); 
        cstmt.registerOutParameter(1, ...Type returned by function); 
        cstmt.setString(2, inputCode); 
        cstmt.registerOutParameter(3, oracle.jdbc.OracleTypes.NUMBER); 
        cstmt.registerOutParameter(4, oracle.jdbc.OracleTypes.VARCHAR); 
        cstmt.registerOutParameter(5, oracle.jdbc.OracleTypes.CHAR); 
        cstmt.registerOutParameter(6, oracle.jdbc.OracleTypes.CHAR); 
        cstmt.executeUpdate(); 
0

tham số trở lại của bạn chỉ có một. cái đầu tiên. đó là người duy nhất bạn phải đăng ký loại của nó. vì vậy, trước tiên, trước tiên:

cstmt.registerOutParameter (1, oracle.jdbc.OracleTypes.VARCHAR);

sau đó thiết lập/đăng ký các thông số khác khi cần thiết, nhưng bạn có 6 thông số như trong dấu hỏi và bạn chỉ xử lý 5. Bạn sẽ cần phải thiết lập một lần thứ 6 cũng như:

cstmt .setString (6, myVariable);

nếu không rõ, vui lòng đăng nguyên mẫu hàm sql bạn đang sử dụng và tôi sẽ chỉ cho bạn thiếu ràng buộc chính xác.

-1

Thực tế có nhiều cách để làm như vậy. Nhưng dễ nhất trong số họ là bắn một truy vấn. Đây là cách thực hiện.

String sql="select myFunction('"+number+"','"+date"') from dual"; 
statement.execute(sql); 

Đặt tham số đầu vào và đầu ra nếu bạn đang sử dụng JDBC.

Nếu bạn đang sử dụng sử dụng Hibernate Đặt tên truy vấn một cái gì đó như thế này: YourMapping.hbm.xml

<sql-query name="my_function" callable="true"> 
<return alias="demo" class="net.bean.Demo"> 
<return-property name="id" column="id"/> 
<return-property name="fname" column="fname"/> 
<return-property name="lname" column="lname"/> 
</return> 
    {?=call demoFunc(:param1,:param2)} 
</sql-query> 

Bây giờ điều này sẽ tạo ra một truy vấn đặt tên cho hàm

Sau đó để làm là chỉ cần gọi nó bằng cách sử dụng mã sau

Query query=session.getNamedQuery("my_function"); 
query.setParameter("parma1",date); 
query.setParameter("parma2",number); 
query.executeUpdate(); 

Lưu ý rằng trong hbm.Tệp xml tên lớp và thuộc tính trả về tồn tại chỉ áp dụng nếu bạn đã ánh xạ các giá trị trả về nếu hàm trả về các giá trị thích hợp.