zoukankan      html  css  js  c++  java
  • JDBC对MySQL数据库存储过程的调用

            一、MySQL数据库存储过程:

            1、什么是存储过程

            存储过程(英文:Stored Procedure)是在大型数据库系统中,为了完毕特定功能而编写的一组的SQL语句集。存储过程经编译存储在数据库中。用户通过指定存储过程的名字并给出參数(假设该存储过程带有參数)来运行它。

            2、与一般SQL语句相比。使用存储过程有哪些长处。有哪些缺点

            长处:
            1)、降低了脚本的运行环节,缩短了获取数据的时间。存储过程仅仅在创建的时进行编译,在调用使用的时候直接运行。不需再次编译;而一般SQL语句每次运行前都须要编译一次,故效率没有存储过程高。
            2)、降低网络传输量,提高了传输速度。

    存储过程编译后存储在数据库server上,使用的时候仅仅须要指定存储过程的名字并给出參数(假设该存储过程带有參数)就能够了;而一般SQL语句须要将所运行语句字符串传输到数据库server端。相比于存储过程而言向数据库服务端传送的字符串长度比較大;
            3)、安全性比較高。为存储过程參数赋值仅仅能使用问号传參的形式(这一点能够通过以下JDBC对MySQL数据库存储过程的调用样例体现出来),这样能够防止SQL注入式攻击;一般SQL语句也能够做到防止SQL注入式攻击,可是并非必须的。能够将Grant、Deny以及Revoke权限应用于存储过程,即言能够设定仅仅有某些用户才具有对指定存储过程的使用权;
            缺点:
            1)、假设在一个程序系统中大量的使用存储过程,当程序交付使用的时候随着客户需求的添加会导致数据结构的变化,接着就是存储过程的改动。这样系统维护就会越来越难而且代价也会越来越大。


            3、如何创建存储过程及创建存储过程须要注意的地方

            存储过程的创建格式为:

            create procedure 存储过程名([[IN |OUT |INOUT ] 參数名 数据类形...])
            begin
            存储过程体
            end

            创建存储过程的详细样例见以下JDBC对MySQL数据库存储过程的调用样例。

            须要注意的地方:见以下JDBC对MySQL数据库存储过程的调用样例内创建存储过程语句中的凝视;

            二、JDBC对MySQL数据库存储过程的调用:

            为了更加直观的介绍JDBC怎样实现对MySQL数据库存储过程的调用,这里直接以样例的形式展示。

            1、没有不论什么输入和输出參数的存储过程

    package com.ghj.packageoftest;
    
    import java.sql.CallableStatement;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import com.ghj.packageoftool.LinkDB;
    
    /*
    运行本程序前需运行的脚本:
    DELIMITER $$//<span style="font-family: Arial, Helvetica, sans-serif;">DELIMITER和$$之间要么没有空格要么仅仅有一个空格,假设有多个空格,在运行创建存储过程语句时你会发现这样是不能创建成功的</span>
    CREATE PROCEDURE noParam()
    BEGIN
    SELECT AVG(price) AS priceAvg FROM fruit;
    END$$
    DELIMITER ;
    */
    
    /**
     * 没有不论什么输入和输出參数的存储过程
     * 
     * @author GaoHuanjie
     */
    public class NoParam {
    	public static void main(String args[]) throws SQLException {
    		Connection connection = LinkDB.getMySqlConnection();
    		String proStr = "{call noParam}";
    		CallableStatement callableStatement = connection.prepareCall(proStr);
    		callableStatement.execute();
    		ResultSet resultSet = callableStatement.getResultSet();
    		while (resultSet.next()) {
    			System.out.println("产品的平均价格是:" + resultSet.getDouble("priceAvg") + "元");
    		}
    		LinkDB.close(connection, callableStatement, resultSet);
    	}
    }

            2、仅仅有两个输入參数的存储过程

    package com.ghj.packageoftest;
    
    import java.sql.CallableStatement;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import com.ghj.packageoftool.LinkDB;
    
    /*
    执行本程序前需执行的脚本:
    DELIMITER $$
    CREATE PROCEDURE inTwoParam(IN fruitName VARCHAR(12),IN fruitPrice DECIMAL(9,2))//说明:fruitPrice參数的数据类型与price列的数据类型不一致(price的类型为(8,2)),对这一现象应该有所感悟。
    BEGIN
    SELECT * FROM fruit WHERE NAME LIKE CONCAT('%',fruitName,'%') AND price < fruitPrice;//注意:CONCAT('%',fruitName,'%')不能为'%'+fruitName+'%'
    END$$
    DELIMITER ;
    */
    
    /**
     * 仅仅有两个输入參数的存储过程
     * 
     * @author GaoHuanjie
     */
    public class InTwoParam {
    	public static void main(String args[]) throws SQLException {
    		Connection connection = LinkDB.getMySqlConnection();
    		String procStr = "{call inTwoParam(?

    ,?)}"; CallableStatement callableStatement = connection.prepareCall(procStr); callableStatement.setString(1, "莲"); callableStatement.setDouble(2, 88.88);//对DECIMAL类型的属性设值要使用setDouble方法。 callableStatement.execute(); ResultSet resultSet = callableStatement.getResultSet(); System.out.println("名称包括‘莲’字且价格小于88.88元的水果有:"); while (resultSet.next()) { System.err.println("名称:" + resultSet.getString("name") +"、价格:" + resultSet.getDouble("price") + "元"+"、产地:" + resultSet.getString("address")); } LinkDB.close(connection, callableStatement, resultSet); } }

            3、仅仅有两个输出參数的存储过程

    package com.ghj.packageoftest;
    
    import java.sql.CallableStatement;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.Types;
    
    import com.ghj.packageoftool.LinkDB;
    
    /*
    执行本程序前需执行的脚本:
    DELIMITER $$
    CREATE PROCEDURE outTwoParam(OUT fruitName VARCHAR(12),OUT fruitPrice DECIMAL(5,3) )
    BEGIN
    SELECT name INTO fruitName FROM fruit WHERE name='莲雾';
    SELECT price INTO fruitPrice FROM fruit WHERE NAME='莲雾';
    END $$
    DELIMITER ;
    注意:上面两条查询语句不能合成一个SQL语句——SELECT NAME INTO fruitName, price INTO fruitPrice FROM fruit WHERE NAME='莲雾';
    */
    
    /**
     * 仅仅有两个输出參数的存储过程
     * 
     * @author GaoHuanjie
     */
    public class OutTwoParam {
    	public static void main(String args[]) throws SQLException {
    		Connection connection = LinkDB.getMySqlConnection();
    		String proStr = "{call outTwoParam(?

    ,?)}"; CallableStatement callableStatement = connection.prepareCall(proStr); callableStatement.registerOutParameter(1, Types.VARCHAR); callableStatement.registerOutParameter(2, Types.DECIMAL); callableStatement.execute(); String fruitName = callableStatement.getString(1); double fruitPrice = callableStatement.getDouble(2);// 获取DECIMAL类型的属性要使用getDouble方法。

    System.out.println("水果名称:" + fruitName +"、水果价格:" + fruitPrice + "元"); LinkDB.close(connection, callableStatement, null); } }

            4、含有一个输入參数和一个输出參数的存储过程

    package com.ghj.packageoftest;
    
    import java.sql.CallableStatement;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.Types;
    
    import com.ghj.packageoftool.LinkDB;
    
    /*
    执行本程序前需执行的脚本:
    DELIMITER $$
    CREATE PROCEDURE inOneParamAndOutOneParam(IN fruitName VARCHAR(12),OUT fruitPrice DECIMAL(7,3))
    BEGIN
    SELECT price FROM fruit WHERE NAME=fruitName INTO fruitPrice;
    END $$
    DELIMITER ;
    */
     
    /**
     * 含有一个输入參数和一个输出參数的存储过程
     * 
     * @author GaoHuanjie
     */
    public class InOneParamAndOutOneParam {
    	public static  void main(String args[]) throws SQLException {
    		Connection connection=LinkDB.getMySqlConnection();
    		CallableStatement callableStatement=null;
    		String procStr="{call inOneParamAndOutOneParam(?

    ,?)}"; callableStatement=connection.prepareCall(procStr); String fruitName = "莲雾"; callableStatement.setString(1, fruitName); callableStatement.registerOutParameter(2, Types.DECIMAL); callableStatement.execute(); double fruitPrice=callableStatement.getDouble(2);//获取DECIMAL类型的属性要使用getDouble方法。

    System.out.println(fruitName+"的价格为:"+fruitPrice+"元"); LinkDB.close(connection, callableStatement, null); } }

            5、输入參数即输出參数的存储过程

    package com.ghj.packageoftest;
    
    import java.sql.*;
    
    import com.ghj.packageoftool.LinkDB;
    
    /*
     执行本程序前需执行的脚本:
    DELIMITER $$
    CREATE PROCEDURE inOneParamISOutOneParam(INOUT fruitName VARCHAR(12))
    BEGIN
    SELECT NAME INTO fruitName FROM fruit WHERE NAME LIKE CONCAT('%', fruitName, '%') LIMIT 0,1;
    END $$
    DELIMITER ;
    或
    DELIMITER $$
    CREATE PROCEDURE inOneParamISOutOneParam(INOUT fruitName VARCHAR(12))
    BEGIN
    SELECT NAME FROM fruit WHERE NAME LIKE CONCAT('%', fruitName, '%') LIMIT 0,1 INTO fruitName;
    END $$
    DELIMITER ;
    
    注意上面查询语句不能这样写:SELECT NAME FROM fruit WHERE NAME LIKE CONCAT('%', fruitName, '%') INTO fruitName LIMIT 0,1;
    注意:对照3、4和5Java文件内创建存储过程脚本中“INTO”keyword的位置你一定深有收获。呵呵呵,偷点懒。在此就不总结了。
    */
    
    /**
     * 输入參数即输出參数的存储过程
     * 
     * @author GaoHuanjie
     */
    public class InOneParamISOutOneParam {
    	public static void main(String args[]) throws SQLException {
    		Connection con = LinkDB.getMySqlConnection();
    		CallableStatement callableStatement = null;
    		String procStr = "{call inOneParamISOutOneParam(?

    )}"; callableStatement = con.prepareCall(procStr); callableStatement.setString(1, "莲"); callableStatement.registerOutParameter(1, Types.VARCHAR); callableStatement.execute(); String fruitName = callableStatement.getString(1); System.out.println("表中水果名称含有‘莲’字的一中水果的名称是:" + fruitName); LinkDB.close(con, callableStatement, null); } }

            说明:

            1、假设把上面代码拷贝下来你会发现缺少LinkDB类,现贴出该类:

    package com.ghj.packageoftool;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * 连接数据库
     * 
     * @author GaoHuanjie
     */
    public class LinkDB {
    
    	/**
    	 * 功能:获取与MySql的连接
    	 * 
    	 * @author GaoHuanjie
    	 */
    	public static Connection getMySqlConnection() {
    		Connection connection = null;
    		String url = "jdbc:mysql://localhost:3306/test";
    		String user = "root";
    		String pwd = "";
    		String driverName = "com.mysql.jdbc.Driver";
    		try {
    			Class.forName(driverName);
    			connection = DriverManager.getConnection(url, user, pwd);
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} 
    		return connection;
    	}
    
    	/**
    	 * 关闭释放全部的资源
    	 * 
    	 * @author GaoHuanjie
    	 */
    	public static void close(Connection con, PreparedStatement ps, ResultSet rs) {
    		if (rs != null){
    			try {
    				rs.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    		if (ps != null){
    			try {
    				ps.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    		if (con != null){
    			try {
    				con.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }

            2、假设运行创建存储过程的SQL脚本,你会发现缺少名为fruit类。现贴出创建该表的SQL语句:

    CREATE DATABASE `test`;
    USE `test`;
    CREATE TABLE `fruit` (
      `id` char(36) NOT NULL COMMENT '标识',
      `name` varchar(12) NOT NULL COMMENT '名称',
      `price` decimal(8,2) NOT NULL COMMENT '单位价格',
      `address` varchar(300) DEFAULT NULL COMMENT '产地',
       PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='水果表';
    
    insert  into `fruit`(`id`,`name`,`price`,`address`) 
    values 
    ('27640c30-8df5-4cf2-916e-c28e0b2b1b52','山竹','24.45','马来西亚'),
    ('46ac8392-9922-4593-89a3-517a9e516733','菠萝','19.41','巴西'),
    ('63061a9f-3a0e-4140-98e0-8b1e13e4eab3','哈密瓜','17.77','中国'),
    ('7ef0c286-b8b1-4e1e-9a8a-36bce703cf18','鳄梨','30.80','墨西哥'),
    ('a1cf5251-9311-4c7f-be10-3532d8c16291','树莓','117.50','瑞士'),
    ('c397aed0-a39a-49c5-91ee-7fc0579ddb20','莲雾','77.33','印度尼西亚'),
    ('e8068fa1-a8e7-4025-89e2-36c1d5d23c74','榴莲','16.50','泰国');

            【0分下载演示资源

  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/jhcelue/p/7019966.html
Copyright © 2011-2022 走看看