JDBC系列 之 存储过程

https://blog.csdn.net/luanlouis/article/details/31376041



前言

      最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解。所以便把JDBC 这个东东翻出来,老调重弹,好好总结一番,作为自己的笔记,也是给读者一个参考~~~

      本文主要通过 使用JDBC创建存储过程 和使用JDBC调用存储过程两部分 阐述JDBC 对存储过程的支持。本文将在Oracle数据库下创建一个可以表示岗位信息的基本表Jobs为例, 然后通过存储过程对这个Jobs表进行各种操作。表JOBS的建表语句如下:

[sql]  view plain  copy
  1. -- Create table  
  2. create table JOBS  
  3. (  
  4.   job_id     VARCHAR2(10) not null,  
  5.   job_title  VARCHAR2(35),  
  6.   min_salary NUMBER(6),  
  7.   max_salary NUMBER(6)  
  8. );  
  9.   
  10. -- Add comments to the table   
  11. comment on table JOBS  
  12.   is '岗位信息表';  
  13. -- Add comments to the columns   
  14. comment on column JOBS.job_id  
  15.   is 'Job Id';  
  16. comment on column JOBS.job_title  
  17.   is '岗位名称';  
  18. comment on column JOBS.min_salary  
  19.   is '最小薪酬';  
  20. comment on column JOBS.max_salary  
  21.   is '最大薪酬';  
  22. -- Create/Recreate primary, unique and foreign key constraints   
  23. alter table JOBS  
  24.   add constraint PK_JOB_ID primary key (JOB_ID);  

JDBC创建存储过程

使用数据库操作数据库需要三个步骤: 执行 创建存储过程语句 --> 编译存储过程---> 调用存储过程

比如我们创建一个向表Jobs添加记录的存储过程,并且调用它,在数据库上要执行下列代码:

[sql]  view plain  copy
  1. --1.创建存储过程  
  2.   
  3. CREATE OR REPLACE PROCEDURE insert_jobs_proc(  
  4.     input_job_id IN VARCHAR2,  
  5.         input_job_title IN VARCHAR2,  
  6.         input_min_salary IN NUMBER,  
  7.         input_max_salary IN NUMBER) AS  
  8. BEGIN  
  9.     INSERT INTO jobs(job_id,job_title,Min_Salary,max_salary)VALUES(input_job_id,input_job_title,input_min_salary,input_max_salary);  
  10. END insert_jobs_proc;  
  11.   
  12. --2.编译存储过程  
  13. COMPILE;  
  14.   
  15. --3.使用存储过程  
  16. CALL insert_jobs_proc('AD_PRES','President',20080,40000);  

由于上述的代码本质上来说就是SQL代码,可以使用JDBC逐步执行上述的SQL代码即可(不过使用JDBC创建不需要调用compile进行编译,JDBC会自动让数据库编译):

[java]  view plain  copy
  1. public static void inTest(){  
  2.       
  3.     Connection connection = null;  
  4.     Statement statement = null;  
  5.     ResultSet resultSet = null;  
  6.       
  7.     try {  
  8.           
  9.         Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();  
  10.           
  11.         Driver driver = DriverManager.getDriver(URL);  
  12.         Properties props = new Properties();  
  13.         props.put("user", USER_NAME);  
  14.         props.put("password", PASSWORD);  
  15.           
  16.         connection = driver.connect(URL, props);  
  17.           
  18.         //获得Statement对象,这里使用了事务机制,如果创建存储过程语句失败或者是执行compile失败,回退  
  19.         connection.setAutoCommit(false);  
  20.         statement = connection.createStatement();  
  21.         String procedureString = "CREATE OR REPLACE PROCEDURE insert_jobs_proc("  
  22.                                      +"input_job_id IN VARCHAR2,"  
  23.                                   +"input_job_title IN VARCHAR2,"  
  24.                                   +"input_min_salary IN NUMBER,"  
  25.                                   +"input_max_salary IN NUMBER) AS "  
  26.                                      +"BEGIN "  
  27.                                   +"INSERT INTO jobs(job_id,job_title,Min_Salary,max_salary)VALUES(input_job_id,input_job_title,input_min_salary,input_max_salary); "  
  28.                                      +"END insert_jobs_proc;";  
  29.         //1 创建存储过程,JDBC 数据库会编译存储过程  
  30.         statement.execute(procedureString);  
  31.         //成功则提交  
  32.         connection.commit();  
  33.         //2.调用  
  34.         CallableStatement callableStatement = connection.prepareCall("CALL insert_jobs_proc(?,?,?,?)");  
  35.         //设置IN参数  
  36.         callableStatement.setString(1"AD_PRESS");  
  37.         callableStatement.setString(2"President");  
  38.         callableStatement.setBigDecimal(3new BigDecimal(20080));  
  39.         callableStatement.setBigDecimal(4new BigDecimal(40000));  
  40.           
  41.         callableStatement.execute();  
  42.         connection.commit();  
  43.           
  44.     } catch (ClassNotFoundException e) {  
  45.         System.out.println("加载Oracle类失败!");  
  46.         e.printStackTrace();  
  47.     } catch (SQLException e) {  
  48.         try {  
  49.             connection.rollback();  
  50.         } catch (SQLException e1) {  
  51.             e1.printStackTrace();  
  52.         }  
  53.         e.printStackTrace();  
  54.     } catch (InstantiationException e) {  
  55.         e.printStackTrace();  
  56.     } catch (IllegalAccessException e) {  
  57.         e.printStackTrace();  
  58.     }finally{  
  59.             //使用完成后管理链接,释放资源,释放顺序应该是: ResultSet ->Statement ->Connection  
  60.               
  61.             try {  
  62.                 statement.close();  
  63.             } catch (SQLException e) {  
  64.                 e.printStackTrace();  
  65.             }  
  66.               
  67.             try {  
  68.                 connection.close();  
  69.             } catch (SQLException e) {  
  70.                 e.printStackTrace();  
  71.             }  
  72.     }  
  73. }  


JDBC调用存储过程

使用JDBC调用存储过程的基本格式为:

CALL PROCEDURE_NAME(parameter1,parameter2,paramter3.....)

这里参数有三种不同的形式 :in 类型、out类型还有 in 和out的混合类型:

IN 类型:此类型是用于参数从外部传递给存储过程使用;

OUT类型:此类型是存储过程执行过程中的返回值;

IN、OUT混合类型:此类型是参数传入,然后返回。

以下分四种参数类型创建不同的存储过程,然后通过JDBC调用:

只有输入IN参数,没有输出OUT参数

 上面演示的存储过程  insert_jobs_proc 就是只有IN 参数传入的例子,请读者看上述的 例子。

既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)

创建一个存储过程  get_job_min_salary_proc,传入特定岗位的job_id,返回输出此岗位的最小薪酬min_salary,对应的SQL语句如下:

[sql]  view plain  copy
  1. CREATE OR REPLACE PROCEDURE get_job_min_salary_proc(  
  2.     input_job_id IN VARCHAR2,  
  3.         output_salary OUT number) AS   
  4. BEGIN  
  5.     SELECT min_salary INTO output_salary FROM jobs WHERE job_id = input_job_id;  
  6. END   get_job_min_salary_proc;  

在JDBC中调用如下:

[java]  view plain  copy
  1. /* 
  2.  * 有IN 类型的参数输入 和Out类型的参数输出   
  3.  */  
  4.     public static void inOutTest(){  
  5.         Connection connection = null;  
  6.         Statement statement = null;  
  7.         ResultSet resultSet = null;  
  8.         try {  
  9.               
  10.             Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();  
  11.               
  12.             Driver driver = DriverManager.getDriver(URL);  
  13.             Properties props = new Properties();  
  14.             props.put("user", USER_NAME);  
  15.             props.put("password", PASSWORD);  
  16.               
  17.             connection = driver.connect(URL, props);  
  18.               
  19.             //获得Statement对象,这里使用了事务机制,如果创建存储过程语句失败或者是执行compile失败,回退  
  20.             connection.setAutoCommit(false);  
  21.             statement = connection.createStatement();  
  22.             String procedureString = "CREATE OR REPLACE PROCEDURE get_job_min_salary_proc("  
  23.                                       +"input_job_id IN VARCHAR2,"  
  24.                                       +"output_salary OUT number) AS "  
  25.                                       +"BEGIN "  
  26.                                       +"SELECT min_salary INTO output_salary FROM jobs WHERE job_id = input_job_id; "  
  27.                                       +"END   get_job_min_salary_proc;";  
  28.             //1 创建存储过程,JDBC 数据库会编译存储过程  
  29.             statement.execute(procedureString);  
  30.             //成功则提交  
  31.             connection.commit();  
  32.             //2.创建callableStatement  
  33.             CallableStatement callableStatement = connection.prepareCall("CALL get_job_min_salary_proc(?,?)");  
  34.             //3,设置in参数  
  35.             callableStatement.setString(1"AD_PRES");  
  36.             //4.注册输出参数  
  37.             callableStatement.registerOutParameter(2, Types.NUMERIC);  
  38.             //5.执行语句  
  39.             callableStatement.execute();  
  40.               
  41.             BigDecimal salary = callableStatement.getBigDecimal(2);  
  42.             System.out.println(salary);  
  43.               
  44.         } catch (ClassNotFoundException e) {  
  45.             System.out.println("加载Oracle类失败!");  
  46.             e.printStackTrace();  
  47.         } catch (SQLException e) {  
  48.             try {  
  49.                 connection.rollback();  
  50.             } catch (SQLException e1) {  
  51.                 e1.printStackTrace();  
  52.             }  
  53.             e.printStackTrace();  
  54.         } catch (InstantiationException e) {  
  55.             e.printStackTrace();  
  56.         } catch (IllegalAccessException e) {  
  57.             e.printStackTrace();  
  58.         }finally{  
  59.                 //使用完成后管理链接,释放资源,释放顺序应该是: ResultSet ->Statement ->Connection  
  60.                   
  61.                 try {  
  62.                     statement.close();  
  63.                 } catch (SQLException e) {  
  64.                     e.printStackTrace();  
  65.                 }  
  66.                   
  67.                 try {  
  68.                     connection.close();  
  69.                 } catch (SQLException e) {  
  70.                     e.printStackTrace();  
  71.                 }  
  72.         }  
  73.     }  
  74.       


既有输入IN参数,也有输出OUT参数,输出是列表

创建一个存储过程 get_min_greater_proc,输入参数 最小薪酬,返回jobs表里最小薪酬不小于此参数的岗位集合。

对应的SQL语句如下:

[sql]  view plain  copy
  1. --创建一个包,自定义一个数据类型 my_cursor  
  2. CREATE OR REPLACE PACKAGE my_package_cursor IS  
  3.  TYPE my_cursor IS REF CURSOR;  
  4. END  my_package_cursor;  
  5.   
  6. --创建 存储过程,通过传入最小薪酬,返回JOBs表内不小于最小薪酬的岗位集合  
  7. CREATE OR REPLACE PROCEDURE get_min_greater_proc(  
  8.      input_min_salary IN NUMBER,  
  9.      setResult OUT my_package_cursor.my_cursor) AS  
  10. BEGIN   
  11.     OPEN    setResult FOR   
  12.      SELECT * FROM jobs WHERE min_salary >= input_min_salary;  
  13. END     get_min_greater_proc;   

JDBC调用代码如下:

[java]  view plain  copy
  1. /* 
  2.  * 有IN 类型的参数输入 和Out类型的集合输出 
  3.  */  
  4.     public static void inOutResultSetTest(){  
  5.         Connection connection = null;  
  6.         Statement statement = null;  
  7.         ResultSet resultSet = null;  
  8.         try {  
  9.               
  10.             Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();  
  11.               
  12.             Driver driver = DriverManager.getDriver(URL);  
  13.             Properties props = new Properties();  
  14.             props.put("user", USER_NAME);  
  15.             props.put("password", PASSWORD);  
  16.             connection = driver.connect(URL, props);  
  17.             //1.创建callableStatement  
  18.             CallableStatement callableStatement = connection.prepareCall("CALL get_min_greater_proc(?,?)");  
  19.             //2,设置in参数  
  20.             callableStatement.setBigDecimal(1new BigDecimal(20000));  
  21.             //3.注册输出参数  
  22.             callableStatement.registerOutParameter(2, OracleTypes.CURSOR);  
  23.             //4.执行语句  
  24.             callableStatement.execute();  
  25.             //返回的是结果集  
  26.             resultSet = (ResultSet)callableStatement.getObject(2);  
  27.               
  28.         } catch (ClassNotFoundException e) {  
  29.             System.out.println("加载Oracle类失败!");  
  30.             e.printStackTrace();  
  31.         } catch (SQLException e) {  
  32.             try {  
  33.                 connection.rollback();  
  34.             } catch (SQLException e1) {  
  35.                 e1.printStackTrace();  
  36.             }  
  37.             e.printStackTrace();  
  38.         } catch (InstantiationException e) {  
  39.             e.printStackTrace();  
  40.         } catch (IllegalAccessException e) {  
  41.             e.printStackTrace();  
  42.         }finally{  
  43.                 //使用完成后管理链接,释放资源,释放顺序应该是: ResultSet ->Statement ->Connection  
  44.                   
  45.                 try {  
  46.                     statement.close();  
  47.                 } catch (SQLException e) {  
  48.                     e.printStackTrace();  
  49.                 }  
  50.                   
  51.                 try {  
  52.                     connection.close();  
  53.                 } catch (SQLException e) {  
  54.                     e.printStackTrace();  
  55.                 }  
  56.         }  
  57.     }  

输入输出参数是同一个(IN OUT)

创建一个存储过程 get_job_info ,传入job_id 返回 job_id ,返回的job_id 是输入的job_id 和对应的job_title 拼接而成。

[sql]  view plain  copy
  1. --创建存储过程 传入job_id 返回job_id  
  2. CREATE OR REPLACE PROCEDURE get_job_info(  
  3.      io_job_id IN OUT VARCHAR2) AS  
  4. BEGIN   
  5.          SELECT job_id ||job_title INTO io_job_id FROM jobs WHERE job_id =io_job_id ;  
  6. END     get_job_info;   

对应的JDBC代码如下:

[java]  view plain  copy
  1. //1.创建callableStatement  
  2.    CallableStatement callableStatement = connection.prepareCall("CALL get_job_info(?)");  
  3.    //2,设置in参数  
  4.    callableStatement.setString(1"AD_PRES");  
  5.    //3.注册输出参数  
  6.    callableStatement.registerOutParameter(1, Types.VARCHAR);  
  7.    //4.执行语句  
  8.    callableStatement.execute();  
  9.    //返回结果  
  10.    String jobId = callableStatement.getString(1);  
  11.    System.out.println(jobId); 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值