//存儲過程create or replace Procere countBySal(
p_sal emp.sal%type,
p_count OUT number
)as
begin
select count(*) into p_count from emp where sal >= p_sql;
end countBySal; //調用步奏import java.sql.CallableStatement; //帶哦用存儲過程所必須的語句借口
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Types;public class EmpUtil {
public static int countBySal(double sal) throws Exception{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url="jdbc:oracle:thin:@localhost:1521:test";
Connection cn=DriverManager.getConnection(url, "scott", "tiger");
String sql="{call countBySal(?,?)}";//調用存儲過程的語句,call後面的就是存儲過程名和需要傳入的參數
CallableStatement cst=cn.prepareCall(sql);
cst.setDouble(1, sal);//設置in參數的值
cst.registerOutParameter(2, Types.INTEGER);//注冊out參數的類型
cst.execute();
int result = cst.getInt(2);
cst.close();
cn.close();
return result;
}
public static void main(String[] args) {
int count;
try {
count = EmpUtil.countBySal(3000);
System.out.println("工資在3000元以上的人數為:"+count);
} catch (Exception e) {
e.printStackTrace();
}
}
② JDBC調用存儲過程,存儲過程中事務回滾,報錯
ConnCloseThread中關閉連接的時候,不是立刻返回的。Connection.close()會觸發Connection.commit(),而因為調用的存儲過程中,存儲過程起了自己的事務,connection.commit()必須等到存儲過程結束才能完成(這個是microsoft論壇上看到的)。如果所有connection.close()都等到tx commit或rollback完成才執行的話,這個問題就不會出現了
從測試結果來看,凡是close connection耗時比execute statement短的,連接(物理連接)都會報出該問題。分析原因:通過weblogic datasource獲取的connection並不是物理connection,而是由weblogic wrapped的connection。這些conection在被close後,並不會關閉物理連接,而只是將物理連接還池。我們對connection的所有操作,最終都會被delegated到底層物理連接上,即commit(),rollback()最終都是在物理連接上執行。如果上面的connection.close(),底層物理連接沒有等到存儲過程事務結束就返回的話,那麼物理連接上應該還帶有此次操作的事務,而weblogic這邊不會關系物理連接的情況,直接將連接放入connection pool供其它客戶端使用。這時候如果設定了test on reserve的話,下次客戶端從data source獲取連接時,weblogic會檢查這個物理連接,作一個select操作的,這個有問題的連接就會暴露出來,也就是上面的異常。這個問題如果使用driver manager來獲取連接的話(如果每次都關閉的話),則不會出現,因為使用的物理連接每次都是不同的。還好,weblogic會幫忙重新創建有問題的連接。原因大概了解了,但這是誰的問題呢? 為什麼connection.close()不等存儲過程的事務結束?
結論:一般而言,我們不建議通過JDBC調用存儲過程的時候,在存儲過程中定義事務,應該將tx的管理工作交給jdbc去做。 non-xa如此,xa亦如此,畢竟事務嵌套了以後,管理起來是個問題,完整性更是個問題。
③ jdbc調用存儲過程為什麼語句不能加分號
如果你在程序裡面寫sql,就不要加分號,在程序裡面編譯器會把分號當做sql本身的一部分,所以會報錯 如果是在查詢工具裡面(比如plsql),這個時候可以加上分號,在工具裡面分號是個分隔符,看到分號就標志著本條sql語句結束了; 當然不加也可以,在工具裡面看不到分號就認為本條sql沒有結束。 比如:你寫了兩條sql,但是沒有用分號隔開,此時,工具會當做一條來執行,只不過會報錯而已。
④ jdbc runscript存儲過程里注釋行沒了
runner.runScript(new FileReader(file)); 程序包或函數處於失效狀態。 需要重新打開pl/sql執行後才可以。
存儲過程是指保存在資料庫並在資料庫端執行的程序。你可以使用特殊的語法在Java類中通過JDBC調用存儲過程。
在調用時,存儲過程的名稱及指定的參數通過JDBC連接發送給DBMS,執行存儲過程並通過連接(如果有)返回結果。
⑤ 關於jdbc調用存儲過程的問題
private CallableStatement call ;
public CallableStatement getCall() {
return call;
}
public void setCall(CallableStatement call) {
this.call = call;
}
public int saveFinanceVoucherRecorded(String userName){
int val = 0 ;
String proc = "" ;
try {
proc = "call p_saveFinanceVoucherRecorded(?)";
call = this.getConnection().prepareCall(proc);
logger.info(proc);
call.setString(1, id);
call.executeUpdate();
val = call.getInt(1);
} catch (Exception e) {
val = 4 ;
e.printStackTrace();
}
return val ;
}
⑥ jdbc如何創建存儲過程
//創建存儲過程,記住關閉對象
importjava.sql.CallableStatement;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.ResultSet;
importjava.sql.SQLException;
importjava.sql.Statement;
publicclassUseSQLDataBase3{
Connectioncon;
Statementstate;
ResultSetrs;
CallableStatementcs;//調用存儲過程使用的介面
Stringurl="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test";
Stringuser="sa";
Stringpassword="";
publicvoidconnectSQL(){
try{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
}catch(ClassNotFoundExceptione){
//TODO自動生成catch塊
e.printStackTrace();
}
try{
con=DriverManager.getConnection(url,user,password);
state=con.createStatement();
//創建存儲過程SQL語句
StringcreateProcere="createprocereSHOW_SUPPLIERS"+
"as"+
"selectSUPPLIERS.SUP_NAME,COFFEES.COF_NAME"+
"fromsuppliers,coffees"+
"wheresuppliers.sup_id=coffees.sup_id"+
"orderbysup_name";
//創建存儲過程
state.executeUpdate("USETEST");
state.executeUpdate(createProcere);
//調用存儲過程
cs=con.prepareCall("{callSHOW_SUPPLIERS}");//創建一個CallableStatement對象來調用資料庫存儲過程
//返回調用的結果集
rs=cs.executeQuery();
//輸出結果
System.out.println("SUPPLIERS.SUP_NAMECOFFEES.COF_NAME");
while(rs.next()){
Stringsup_name=rs.getString(1);
Stringcoffees_name=rs.getString(2);
System.out.println(sup_name+""+coffees_name);
}
con.close();
state.close();
}catch(SQLExceptione){
//TODO自動生成catch塊
e.printStackTrace();
}
}
⑦ 1,如何在JDBC裡面調用一個存儲過程
最近做一個自動發郵件的schele,由於取數據的sql太長,直接分割很麻煩,就想到調用PL/SQL,網上查了資料做了練習,在此做下小結。
1、只有輸入參數而沒有返回結果的存儲過程。
sql:
1 create or replace procere prc_1(deptno in number,dname in varchar2,loc in varchar2)
2 is
3 begin
4 insert into dept values(deptno,dname,loc);
5 end prc_1;
java:
1 static void test1(){
2 Connection conn=null;
3 CallableStatement csmt=null;
4 try {
5 conn=JDBCUtils.getConnection();
6 conn.setAutoCommit(false);
7 csmt=conn.prepareCall("call prc_1(?,?,?)");
8 csmt.setInt(1,80);
9 csmt.setString(2,"ioc");
10 csmt.setString(3,"fhp");
11 csmt.execute();
12 conn.commit();
13 System.out.println("success insert data");
14 } catch (SQLException e) {
15 e.printStackTrace();
16 }
17 }
2、有輸入參數且有一個返回值的存儲過程。
sql:
1 create or replace procere prc_2(p_deptno in number,p_loc out varchar2) is
2 begin
3 select loc into p_loc from dept where deptno=p_deptno;
4 end prc_2;
⑧ 通過jdbc怎麼調用存儲過程
使用 JDBC 驅動程序調用不帶參數的存儲過程時,必須使用 call SQL 轉義序列,ResultSet rs = stmt.executeQuery("{call dbo.ProcereName}"); 調用帶參數的存儲過程時,必須結合 SQLServerConnection 類的 prepareCall 方法使用 call SQL 轉義序列 CallableStatement cstmt = con.prepareCall("{call dbo.ProcereName(?, ?)}"); cstmt.setInt(1, java.sql.Types.INTEGER); cstmt.registerOutParameter(2, java.sql.Types.VARCHAR); cstmt.execute(); System.out.println("MANAGER ID: " + cstmt.getInt(1));System.out.println("MANAGER NAME: " + cstmt.getInt(2));
⑨ 如何通過jdbc 讀取 存儲過程
給你個例子把,一看就明白了……
public List queryQYRBB(String date) throws ParseException {
CallableStatement proc = null;
List list = new ArrayList();
DbBean dbBean = new DbBean();
try {
proc = dbBean.conn.prepareCall("{call dbo.pr_YSumReport(?,?)}");
***********dbo.pr_YSumReport為存儲過程的名字************
proc.setString(1, date);
proc.setString(2, Util.getNextDay(date));
proc.execute();
ResultSet rs = proc.executeQuery();
list = dbBean.toListResultSet(rs);
} catch (SQLException e) {
e.printStackTrace();
} finally{
dbBean.close();
}
return list;
}
⑩ JDBC執行存儲過程異常慢
1.connection不知道你是採用什麼方式獲取的,如果不是從連接池裡取,你每connection.close()一次,下次get的時候會重新建立實際物理鏈接,這樣會相當耗時。所以你檢查一下是在獲取connection時耗的時間多,還是在execute的時間多。代碼:
long startTime = System.currentTimeMillis();
conn = getConnection(); // execute();
long endTime = System.currentTimeMillis();
System.out.println("獲取鏈接的時間:" + (endTime - startTime));
執行的類似;
2.從你的存儲過程的邏輯來說,要條件查詢,更新某個欄位的值,和入庫,這三個步驟應該有輸入參數的,那麼你的這個參數是怎麼傳入的?
個人覺得你的這個存儲過程可以優化成SQL來執行,效率應該會更好:
首先,你把輸入參數放入一個臨時表;
比如結構是:
_id _field
查詢的條件 更新的欄位
// 更新_table中存在的記錄的_field欄位,並且只更新_table與_tmp鍵值相等的記錄
UPDATE _table t SET _field=(SELECT MAX(_field) FROM _tmp WHERE _id=t._id) WHERE EXISTS (SELECT 'X' FROM _tmp WHERE _id=t._id);
// 選擇_table與_tmp鍵值不相等的記錄(即_table中不存在的記錄)插入_table
INSERT INTO _table (_id,_field) (SELECT _id,_field FROM _tmp t WHERE NOT EXISTS (SELECT 'X' FROM _table WHERE _id=t._id));
這樣的話,每次都是兩個批量操作,而且不需要輸入參數,直接調用就可以,唯一需要多做的工作就是做臨時表。