//存储过程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));
这样的话,每次都是两个批量操作,而且不需要输入参数,直接调用就可以,唯一需要多做的工作就是做临时表。