首页 > 其他分享 >JDBC 调用自定义函数(常说的存储过程)的步骤

JDBC 调用自定义函数(常说的存储过程)的步骤

时间:2023-04-19 09:01:20浏览次数:39  
标签:JDBC log 自定义 数据库 error try SQL catch 常说

 

平常说的存储过程(Procedure),严格意义上是自定义函数,所以这里以【自定义函数】为名,简称【函数(function)】。

 

package com.joyupx.jdbc;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * 存储过程严格意义上叫【自定义函数】更适宜。
 * 我们这里就叫【自定义函数】,即在数据库中创建的函数,与数据库提供的函数并列。
 */
@Slf4j
public class JDBC_Call_SelfDefinedFunction {

    /**
     * 调用自定义的函数
     */
    @Test
    public void test_call_selfDefined_function () {
        /**
         * 第一步、获取数据库的配置
         */
        InputStream databaseConfigInputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties") ; // 从【类路径】中获取配置文件
        Properties databaseConfigProperties = new Properties();
        try {
            databaseConfigProperties.load(databaseConfigInputStream);   // 加载【数据库】配置文件
        } catch (IOException e) {
            log.error("加载【数据库配置文件】失败!", e);

            return;
        }

        String username = databaseConfigProperties.getProperty("username");
        String password = databaseConfigProperties.getProperty("password");
        String jdbcURL = databaseConfigProperties.getProperty("jdbcURL");
        String jdbcDriver = databaseConfigProperties.getProperty("jdbcDriver");

        /**
         * 第二步、注册驱动
         */
        try {
            Class.forName(jdbcDriver);
        } catch (ClassNotFoundException e) {
            log.error("没有找到数据库的驱动!", e);

            return ;
        }

        /**
         * 第三步、获取数据库的连接
         */
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(jdbcURL, username, password);
        } catch (SQLException e) {
            log.error("获取 Java 程序与数据库服务端程序的连接对象 - 失败!", e);

            return ;
        }

        /**
         * 第四步、编写(与业务密切相关的)SQL,具体到这里是插入数据的 SQL。
         */
        String functionSQL = "{ call `artron-trade`.`firstSDF` }";  // 如果无参数可省略末尾的小括号(小括号表示的函数)。

        /**
         * 第五步、创建 SQL 的【可调用的声明】对象,用于对 SQL 语句做准备工作。
         */
        CallableStatement callableStatement = null;
        try {
            callableStatement = connection.prepareCall(functionSQL);
        } catch (SQLException e) {
            log.error("创建 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第六步:为参数值填充参数据。
         */
        int updatedCount = 0;
        int count = 0;

        /**
         * 第七步、执行 SQL 更新操作并获取受影响的行数,具体到此处为执行向数据表中添加数据操作并获取添加成功的行数。
         */
        try {
            callableStatement.execute();
        } catch (SQLException e) {
            log.error("执行 SQL 更新(具体到这里是向数据表中添加数据) - 失败!", e);

            return;
        }

        ResultSet resultSet = null;
        try {
            resultSet = callableStatement.getResultSet();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        /**
         * 第七步、解析结果;具体到此处是解析查询到的结果集。
         */
        if (null != resultSet) {
            try {
                while (resultSet.next()) {
                    count = resultSet.getInt(1);
                    log.info("记录数 = {}", count);
                }
            } catch (Exception e) {
                log.error("迭代结果集出错了!", e);
            }
        }

        /**
         * 第八步:解析结果,具体到这里为显示插入成功的记录数
         */
        if (0 < updatedCount)
            log.info("成功插入 {} 条数据。", updatedCount);

        /**
         * 第九步、关闭 SQL 的【可调用的声明】对象。
         */
        try {
            callableStatement.close();
        } catch (SQLException e) {
            log.error("关闭 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第十步、断开与数据库的连接。
         */
        try {
            connection.close();
        } catch (SQLException e) {
            log.error("关闭 Java 程序与数据库服务端程序的连接 - 失败!", e);
        }
    }

    /**
     * 调用自定义的函数
     */
    @Test
    public void test_call_selfDefined_function_2 () {
        /**
         * 第一步、获取数据库的配置
	 * DELIMITER $$
	*
	 * USE `数据库名`$$
	 *
	 * DROP PROCEDURE IF EXISTS `queryChinaRegion`$$
	 *
	 * CREATE DEFINER=`用户名`@`%` PROCEDURE `queryChinaRegion`(parentId INT)
	 * BEGIN
	 * 		SELECT * FROM `数据库名`.`t_china_region` r WHERE  r.`parentId` = parentId;
	 * 	END$$
	 *
	 * DELIMITER ;
         */
        InputStream databaseConfigInputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties") ; // 从【类路径】中获取配置文件
        Properties databaseConfigProperties = new Properties();
        try {
            databaseConfigProperties.load(databaseConfigInputStream);   // 加载【数据库】配置文件
        } catch (IOException e) {
            log.error("加载【数据库配置文件】失败!", e);

            return;
        }

        String username = databaseConfigProperties.getProperty("username");
        String password = databaseConfigProperties.getProperty("password");
        String jdbcURL = databaseConfigProperties.getProperty("jdbcURL");
        String jdbcDriver = databaseConfigProperties.getProperty("jdbcDriver");

        /**
         * 第二步、注册驱动
         */
        try {
            Class.forName(jdbcDriver);
        } catch (ClassNotFoundException e) {
            log.error("没有找到数据库的驱动!", e);

            return ;
        }

        /**
         * 第三步、获取数据库的连接
         */
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(jdbcURL, username, password);
        } catch (SQLException e) {
            log.error("获取 Java 程序与数据库服务端程序的连接对象 - 失败!", e);

            return ;
        }

        /**
         * 第四步、编写(与业务密切相关的)SQL,具体到这里是插入数据的 SQL。
         */
        String functionSQL = "{ call `数据库名`.`queryChinaRegion`( ? ) }";

        /**
         * 第五步、创建 SQL 的【可调用的声明】对象,用于对 SQL 语句做准备工作。
         */
        CallableStatement callableStatement = null;
        try {
            callableStatement = connection.prepareCall(functionSQL);
        } catch (SQLException e) {
            log.error("创建 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第六步:为参数值填充参数据。
         */
        int id = 1;
        id = 2;
        id = 3;
        id = 38;
        try {
            callableStatement.setInt(1, id);
        } catch (SQLException e) {
            log.error("为参数值填充数据 - 失败!", e);

            return;
        }

        /**
         * 第七步、执行 SQL 更新操作并获取受影响的行数,具体到此处为执行向数据表中添加数据操作并获取添加成功的行数。
         */
        try {
            callableStatement.execute();
        } catch (SQLException e) {
            log.error("执行 SQL 更新(具体到这里是向数据表中添加数据) - 失败!", e);

            return;
        }

        /**
         * 第八步、获取结果
         */
        ResultSet resultSet = null;
        try {
            resultSet = callableStatement.getResultSet();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        /**
         * 第九步、解析结果;具体到此处是解析查询到的结果集。
         */
        if (null != resultSet) {
            try {
                while (resultSet.next()) {
                    int id_ = resultSet.getInt(1);
                    int parentId = resultSet.getInt("parentId");
                    byte type = resultSet.getByte("type");
                    String code = resultSet.getString("code");
                    String name = resultSet.getString("name");

                    log.info("ID = {}, \t父 ID = {}, \t类别 = {}, \t编号:{}, \t名称:{}"
                            , id_, parentId, type, code, name);
                }
            } catch (Exception e) {
                log.error("迭代结果集出错了!", e);
            }
        }

        /**
         * 第十步、关闭 SQL 的【可调用的声明】对象。
         */
        try {
            callableStatement.close();
        } catch (SQLException e) {
            log.error("关闭 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第十一步、断开与数据库的连接。
         */
        try {
            connection.close();
        } catch (SQLException e) {
            log.error("关闭 Java 程序与数据库服务端程序的连接 - 失败!", e);
        }
    }

    /**
     * 调用自定义的【加法】函数
     *
     * <note>
     * USE `数据库名`;
     * SELECT DATABASE();
     * DROP PROCEDURE IF EXISTS `add`;
     * CREATE DEFINER=`用户名`@`%` PROCEDURE `add`(number1 INT, number2 INT, OUT result INT) BEGIN SET result = number1 + number2 ; END;
     * SELECT `SPECIFIC_NAME` FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE `ROUTINE_SCHEMA` = '数据库名' AND ROUTINE_TYPE = 'PROCEDURE';
     * </note>
     */
    @Test
    public void test_call_function_add () {
        /**
         * 第一步、获取数据库的配置
         */
        InputStream databaseConfigInputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties") ; // 从【类路径】中获取配置文件
        Properties databaseConfigProperties = new Properties();
        try {
            databaseConfigProperties.load(databaseConfigInputStream);   // 加载【数据库】配置文件
        } catch (IOException e) {
            log.error("加载【数据库配置文件】失败!", e);

            return;
        }

        String username = databaseConfigProperties.getProperty("username");
        String password = databaseConfigProperties.getProperty("password");
        String jdbcURL = databaseConfigProperties.getProperty("jdbcURL");
        String jdbcDriver = databaseConfigProperties.getProperty("jdbcDriver");

        /**
         * 第二步、注册驱动
         */
        try {
            Class.forName(jdbcDriver);
        } catch (ClassNotFoundException e) {
            log.error("没有找到数据库的驱动!", e);

            return ;
        }

        /**
         * 第三步、获取数据库的连接
         */
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(jdbcURL, username, password);
        } catch (SQLException e) {
            log.error("获取 Java 程序与数据库服务端程序的连接对象 - 失败!", e);

            return ;
        }

        /**
         * 第四步、编写(与业务密切相关的)SQL,具体到这里是调用【加法】自定义函数(常被称为存储过程)的 SQL。
         */
        String functionSQL = "{ call `数据库名`.`add`( ?, ?, ? ) }";

        /**
         * 第五步、创建 SQL 的【可调用的声明】对象,用于对 SQL 语句做准备工作。
         */
        CallableStatement callableStatement = null;
        try {
            callableStatement = connection.prepareCall(functionSQL);
        } catch (SQLException e) {
            log.error("创建 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第六步:为参数值填充参数据。
         */
        int number1 = 2;
        int number2 = 3;
        try {
            callableStatement.setInt(1, number1);
            callableStatement.setInt(2, number2);
            callableStatement.registerOutParameter(3, Types.INTEGER);
        } catch (SQLException e) {
            log.error("为参数值填充数据 - 失败!", e);

            return;
        }

        /**
         * 第七步、执行 SQL 更新操作并获取受影响的行数,具体到此处为执行向数据表中添加数据操作并获取添加成功的行数。
         */
        try {
            callableStatement.execute();
        } catch (SQLException e) {
            log.error("执行 SQL 更新(具体到这里是向数据表中添加数据) - 失败!", e);

            return;
        }

        /**
         * 第八步、获取结果
         */
        int sum = 0;
        try {
            sum = callableStatement.getInt(3);
        } catch (SQLException e) {
            log.error("获取整型结果 - 失败!", e);
        }

        /**
         * 第九步、解析结果;具体到此处是解析查询到的结果集。
         */
        log.info("和 = {}", sum);

        /**
         * 第十步、关闭 SQL 的【可调用的声明】对象。
         */
        try {
            callableStatement.close();
        } catch (SQLException e) {
            log.error("关闭 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第十一步、断开与数据库的连接。
         */
        try {
            connection.close();
        } catch (SQLException e) {
            log.error("关闭 Java 程序与数据库服务端程序的连接 - 失败!", e);
        }
    }

    /**
     * 调用自定义的【减法】函数
     *
     * <note>
     * SHOW PROCEDURE STATUS WHERE db = '数据库名' AND NAME = 'subtract';
     * CREATE PROCEDURE `数据库名`.`subtract`( IN minuend FLOAT, IN subtrahend FLOAT, OUT difference FLOAT ) BEGIN SET difference = minuend - subtrahend ; END;
     * SELECT `SPECIFIC_NAME` FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE `ROUTINE_SCHEMA` = '数据库名' AND ROUTINE_TYPE = 'PROCEDURE';
     * SHOW CREATE PROCEDURE `数据库名`.`subtract`;
     * </note>
     */
    @Test
    public void test_call_function_subtract () {
        /**
         * 第一步、获取数据库的配置
         */
        InputStream databaseConfigInputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties") ; // 从【类路径】中获取配置文件
        Properties databaseConfigProperties = new Properties();
        try {
            databaseConfigProperties.load(databaseConfigInputStream);   // 加载【数据库】配置文件
        } catch (IOException e) {
            log.error("加载【数据库配置文件】失败!", e);

            return;
        }

        String username = databaseConfigProperties.getProperty("username");
        String password = databaseConfigProperties.getProperty("password");
        String jdbcURL = databaseConfigProperties.getProperty("jdbcURL");
        String jdbcDriver = databaseConfigProperties.getProperty("jdbcDriver");

        /**
         * 第二步、注册驱动
         */
        try {
            Class.forName(jdbcDriver);
        } catch (ClassNotFoundException e) {
            log.error("没有找到数据库的驱动!", e);

            return ;
        }

        /**
         * 第三步、获取数据库的连接
         */
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(jdbcURL, username, password);
        } catch (SQLException e) {
            log.error("获取 Java 程序与数据库服务端程序的连接对象 - 失败!", e);

            return ;
        }

        /**
         * 第四步、编写(与业务密切相关的)SQL,具体到这里是调用【减法】自定义函数(常被称为存储过程)的 SQL。
         */
        String functionSQL = "{ call `数据库名`.`subtract`( ?, ?, ? ) }";

        /**
         * 第五步、创建 SQL 的【可调用的声明】对象,用于对 SQL 语句做准备工作。
         */
        CallableStatement callableStatement = null;
        try {
            callableStatement = connection.prepareCall(functionSQL);
        } catch (SQLException e) {
            log.error("创建 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第六步:为参数值填充参数据。
         */
        float minuend = 2.3f;
        float subtrahend = 3.5f;
        try {
            callableStatement.setFloat(1, minuend);
            callableStatement.setFloat(2, subtrahend);
            callableStatement.registerOutParameter(3, Types.FLOAT);
        } catch (SQLException e) {
            log.error("为参数值填充数据 - 失败!", e);

            return;
        }

        /**
         * 第七步、执行 SQL 更新操作并获取受影响的行数,具体到此处为执行向数据表中添加数据操作并获取添加成功的行数。
         */
        try {
            callableStatement.execute();
        } catch (SQLException e) {
            log.error("执行 SQL 更新(具体到这里是向数据表中添加数据) - 失败!", e);

            return;
        }

        /**
         * 第八步、获取结果
         */
        float difference = 0;
        try {
            difference = callableStatement.getFloat(3);
        } catch (SQLException e) {
            log.error("获取整型结果 - 失败!", e);
        }

        /**
         * 第九步、解析结果;具体到此处是解析查询到的结果集。
         */
        log.info("差 = {}", difference);

        /**
         * 第十步、关闭 SQL 的【可调用的声明】对象。
         */
        try {
            callableStatement.close();
        } catch (SQLException e) {
            log.error("关闭 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第十一步、断开与数据库的连接。
         */
        try {
            connection.close();
        } catch (SQLException e) {
            log.error("关闭 Java 程序与数据库服务端程序的连接 - 失败!", e);
        }
    }

    /**
     * 调用自定义的【乘法】函数
     *
     * <note>
     * SHOW PROCEDURE STATUS WHERE db = '数据库名' AND NAME = 'multiply';
     *
     * CREATE PROCEDURE `数据库名`.`multiply`( IN multiplicand DOUBLE, IN multiplier DOUBLE, OUT product DOUBLE) BEGIN SET product = multiplicand * multiplier ; END;
     *
     * SELECT `SPECIFIC_NAME` FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE `ROUTINE_SCHEMA` = '数据库名' AND ROUTINE_TYPE = 'PROCEDURE';
     * </note>
     */
    @Test
    public void test_call_function_multiply () {
        /**
         * 第一步、获取数据库的配置
         */
        InputStream databaseConfigInputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties") ; // 从【类路径】中获取配置文件
        Properties databaseConfigProperties = new Properties();
        try {
            databaseConfigProperties.load(databaseConfigInputStream);   // 加载【数据库】配置文件
        } catch (IOException e) {
            log.error("加载【数据库配置文件】失败!", e);

            return;
        }

        String username = databaseConfigProperties.getProperty("username");
        String password = databaseConfigProperties.getProperty("password");
        String jdbcURL = databaseConfigProperties.getProperty("jdbcURL");
        String jdbcDriver = databaseConfigProperties.getProperty("jdbcDriver");

        /**
         * 第二步、注册驱动
         */
        try {
            Class.forName(jdbcDriver);
        } catch (ClassNotFoundException e) {
            log.error("没有找到数据库的驱动!", e);

            return ;
        }

        /**
         * 第三步、获取数据库的连接
         */
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(jdbcURL, username, password);
        } catch (SQLException e) {
            log.error("获取 Java 程序与数据库服务端程序的连接对象 - 失败!", e);

            return ;
        }

        /**
         * 第四步、编写(与业务密切相关的)SQL,具体到这里是调用【乘法】自定义函数(常被称为存储过程)的 SQL。
         */
        String functionSQL = "{ call `数据库名`.`multiply`( ?, ?, ? ) }";

        /**
         * 第五步、创建 SQL 的【可调用的声明】对象,用于对 SQL 语句做准备工作。
         */
        CallableStatement callableStatement = null;
        try {
            callableStatement = connection.prepareCall(functionSQL);
        } catch (SQLException e) {
            log.error("创建 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第六步:为参数值填充参数据。
         */
        double multiplicand = 2.3f;
        double multiplier = 3.5f;
        try {
            callableStatement.setDouble(1, multiplicand);
            callableStatement.setDouble(2, multiplier);
            callableStatement.registerOutParameter(3, Types.DOUBLE);
        } catch (SQLException e) {
            log.error("为参数值填充数据 - 失败!", e);

            return;
        }

        /**
         * 第七步、执行 SQL 更新操作并获取受影响的行数,具体到此处为执行向数据表中添加数据操作并获取添加成功的行数。
         */
        try {
            callableStatement.execute();
        } catch (SQLException e) {
            log.error("执行 SQL 更新(具体到这里是向数据表中添加数据) - 失败!", e);

            return;
        }

        /**
         * 第八步、获取结果
         */
        double product = 0;
        try {
            product = callableStatement.getDouble(3);
        } catch (SQLException e) {
            log.error("获取整型结果 - 失败!", e);
        }

        /**
         * 第九步、解析结果;具体到此处是解析查询到的结果集。
         */
        log.info("积 = {}", product);

        /**
         * 第十步、关闭 SQL 的【可调用的声明】对象。
         */
        try {
            callableStatement.close();
        } catch (SQLException e) {
            log.error("关闭 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第十一步、断开与数据库的连接。
         */
        try {
            connection.close();
        } catch (SQLException e) {
            log.error("关闭 Java 程序与数据库服务端程序的连接 - 失败!", e);
        }
    }

    /**
     * 调用自定义的【除法】函数
     *
     * <note>
     * CREATE PROCEDURE `数据库名`.`divide`( IN dividend BIGINT, IN divisor BIGINT, OUT quotient BIGINT) BEGIN SET quotient = dividend / divisor ; END;
     *
     * SELECT `SPECIFIC_NAME` FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE `ROUTINE_SCHEMA` = '数据库名' AND ROUTINE_TYPE = 'PROCEDURE';
     * </note>
     */
    @Test
    public void test_call_function_divide () {
        /**
         * 第一步、获取数据库的配置
         */
        InputStream databaseConfigInputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties") ; // 从【类路径】中获取配置文件
        Properties databaseConfigProperties = new Properties();
        try {
            databaseConfigProperties.load(databaseConfigInputStream);   // 加载【数据库】配置文件
        } catch (IOException e) {
            log.error("加载【数据库配置文件】失败!", e);

            return;
        }

        String username = databaseConfigProperties.getProperty("username");
        String password = databaseConfigProperties.getProperty("password");
        String jdbcURL = databaseConfigProperties.getProperty("jdbcURL");
        String jdbcDriver = databaseConfigProperties.getProperty("jdbcDriver");

        /**
         * 第二步、注册驱动
         */
        try {
            Class.forName(jdbcDriver);
        } catch (ClassNotFoundException e) {
            log.error("没有找到数据库的驱动!", e);

            return ;
        }

        /**
         * 第三步、获取数据库的连接
         */
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(jdbcURL, username, password);
        } catch (SQLException e) {
            log.error("获取 Java 程序与数据库服务端程序的连接对象 - 失败!", e);

            return ;
        }

        /**
         * 第四步、编写(与业务密切相关的)SQL,具体到这里是调用【除法】自定义函数(常被称为存储过程)的 SQL。
         */
        String functionSQL = "{ call `数据库名`.`divide`( ?, ?, ? ) }";

        /**
         * 第五步、创建 SQL 的【可调用的声明】对象,用于对 SQL 语句做准备工作。
         */
        CallableStatement callableStatement = null;
        try {
            callableStatement = connection.prepareCall(functionSQL);
        } catch (SQLException e) {
            log.error("创建 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第六步:为参数值填充参数据。
         */
        long dividend = 6;
        long divisor = 3;
        try {
            callableStatement.setLong(1, dividend);
            callableStatement.setLong(2, divisor);
            callableStatement.registerOutParameter(3, Types.BIGINT);
        } catch (SQLException e) {
            log.error("为参数值填充数据 - 失败!", e);

            return;
        }

        /**
         * 第七步、执行 SQL 更新操作并获取受影响的行数,具体到此处为执行向数据表中添加数据操作并获取添加成功的行数。
         */
        try {
            callableStatement.execute();
        } catch (SQLException e) {
            log.error("执行 SQL 更新(具体到这里是向数据表中添加数据) - 失败!", e);

            return;
        }

        /**
         * 第八步、获取结果
         */
        long quotient = 0;
        try {
            quotient = callableStatement.getLong(3);
        } catch (SQLException e) {
            log.error("获取整型结果 - 失败!", e);
        }

        /**
         * 第九步、解析结果;具体到此处是解析查询到的结果集。
         */
        log.info("商 = {}", quotient);

        /**
         * 第十步、关闭 SQL 的【可调用的声明】对象。
         */
        try {
            callableStatement.close();
        } catch (SQLException e) {
            log.error("关闭 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第十一步、断开与数据库的连接。
         */
        try {
            connection.close();
        } catch (SQLException e) {
            log.error("关闭 Java 程序与数据库服务端程序的连接 - 失败!", e);
        }
    }

    /**
     * 调用自定义的【除法】函数
     *
     * <note>
     * SHOW PROCEDURE STATUS WHERE db = '数据库名' AND NAME = 'mod';
     *
     * DELIMITER ;
     *
     * CREATE PROCEDURE `数据库名`.`mod`( IN n1 TINYINT, IN n2 TINYINT, OUT n3 TINYINT) BEGIN SET n3 = n1 % n2 ; END;
     *
     * DELIMITER ;
     *
     * SELECT `SPECIFIC_NAME` FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE `ROUTINE_SCHEMA` = '数据库名' AND ROUTINE_TYPE = 'PROCEDURE';
     *
     * SHOW CREATE PROCEDURE `数据库名`.`mod`;
     * </note>
     */
    @Test
    public void test_call_function_mod () {
        /**
         * 第一步、获取数据库的配置
         */
        InputStream databaseConfigInputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties") ; // 从【类路径】中获取配置文件
        Properties databaseConfigProperties = new Properties();
        try {
            databaseConfigProperties.load(databaseConfigInputStream);   // 加载【数据库】配置文件
        } catch (IOException e) {
            log.error("加载【数据库配置文件】失败!", e);

            return;
        }

        String username = databaseConfigProperties.getProperty("username");
        String password = databaseConfigProperties.getProperty("password");
        String jdbcURL = databaseConfigProperties.getProperty("jdbcURL");
        String jdbcDriver = databaseConfigProperties.getProperty("jdbcDriver");

        /**
         * 第二步、注册驱动
         */
        try {
            Class.forName(jdbcDriver);
        } catch (ClassNotFoundException e) {
            log.error("没有找到数据库的驱动!", e);

            return ;
        }

        /**
         * 第三步、获取数据库的连接
         */
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(jdbcURL, username, password);
        } catch (SQLException e) {
            log.error("获取 Java 程序与数据库服务端程序的连接对象 - 失败!", e);

            return ;
        }

        /**
         * 第四步、编写(与业务密切相关的)SQL,具体到这里是调用【求余】自定义函数(常被称为存储过程)的 SQL。
         */
        String functionSQL = "{ call `数据库名`.`mod`( ?, ?, ? ) }";

        /**
         * 第五步、创建 SQL 的【可调用的声明】对象,用于对 SQL 语句做准备工作。
         */
        CallableStatement callableStatement = null;
        try {
            callableStatement = connection.prepareCall(functionSQL);
        } catch (SQLException e) {
            log.error("创建 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第六步:为参数值填充参数据。
         */
        byte n1 = 99;
        byte n2 = 10;
        try {
            callableStatement.setByte(1, n1);
            callableStatement.setByte(2, n2);
            callableStatement.registerOutParameter(3, Types.TINYINT);
        } catch (SQLException e) {
            log.error("为参数值填充数据 - 失败!", e);

            return;
        }

        /**
         * 第七步、执行 SQL 更新操作并获取受影响的行数,具体到此处为执行向数据表中添加数据操作并获取添加成功的行数。
         */
        try {
            callableStatement.execute();
        } catch (SQLException e) {
            log.error("执行 SQL 更新(具体到这里是向数据表中添加数据) - 失败!", e);

            return;
        }

        /**
         * 第八步、获取结果
         */
        byte n3 = 0;
        try {
            n3 = callableStatement.getByte(3);
        } catch (SQLException e) {
            log.error("获取整型结果 - 失败!", e);
        }

        /**
         * 第九步、解析结果;具体到此处是解析查询到的结果集。
         */
        log.info("余 = {}", n3);

        /**
         * 第十步、关闭 SQL 的【可调用的声明】对象。
         */
        try {
            callableStatement.close();
        } catch (SQLException e) {
            log.error("关闭 SQL【可调用的声明】对象 - 失败!", e);

            return;
        }

        /**
         * 第十一步、断开与数据库的连接。
         */
        try {
            connection.close();
        } catch (SQLException e) {
            log.error("关闭 Java 程序与数据库服务端程序的连接 - 失败!", e);
        }
    }

}

  

标签:JDBC,log,自定义,数据库,error,try,SQL,catch,常说
From: https://www.cnblogs.com/hapday/p/17332013.html

相关文章

  • swift 自定义tabbar为基本结构的项目
    swift自定义tabbar1、Xcode新建一个项目,选择布局方式为storyBoard,语言为swift2、打开项目,新建一个cocoa文件,继承于TabBarViewController,名字命名为BaseTabBarViewController3、勾选mainstoryboard,选中右侧窗口第四个检查项,将Class关联到BaseTabBarViewController4、新建......
  • Android 自定义View 之 圆环进度条
    圆环进度条前言正文一、XML样式二、构造方法三、测量四、绘制①绘制进度条背景②绘制进度③绘制文字五、API方法六、使用七、源码前言  很多时候我们会使用进度条,而Android默认的进度条是长条的,从左至右。而在日常开发中,有时候UI为了让页面更美观,就需要用到圆环进度条,那么本文......
  • PBI 使用自定义Json
     let查询2=Json.Document(Binary.Decompress(Binary.FromText("i45WMjYwUNJRMjLUdSwoAjJMLYyUYnWilUywCMcCAA==",BinaryEncoding.Base64),Compression.Deflate))in查询2 ......
  • 之于言者博客的自定义样式
    试着瞎搞一点花里胡哨的东西,至于可能出现的效果那就听天由命了。先把代码放在这里,以供来人针砭。本帖有时间的话会同步更新。body:before{/*来自https://www.cnblogs.com/zouwangblog/p/11139344.html*/background:url(https://images.cnblogs.com/cnblogs_com/blogs/79......
  • vue3微信公众号商城项目实战系列(7)自定义底部tabbar组件
    在开始之前,先看看官方对组件的定义: vue3的生态非常丰富,有各种各样的开源组件库可以拿来就用,比如vant、element-ui等,本系列不使用任何第3方组件,完全使用原生的语法来写,只为聚焦vue3技术本身,本篇写一个自定义tabbar组件,效果如下图所示:要实现如下功能:1.底部tab项固定3个:首页......
  • 视频剪辑软件,制作画中画,自定义中画的位置、按比例缩放尺寸
    最近有很多朋友在问,如何剪辑视频,比如说给多个视频制作画中画特效,该如何实现呢?今天小编给大家分享一个新的剪辑技巧,下面一起来试试。所需工具安装一个媒体梦工厂视频素材若干操作步骤步骤1:运行【媒体梦工厂】,在“画中画”中,依次导入视频素材作为底画和中画步骤2:然后设定中画在底画的......
  • zabbix agent自定义监控项,监控交换机vlan流量
    脚本目的:需要对华为ac中的ssid流量进行监控,但acweb页面中与snmp取值差异很大。正好ac的用户流量配置了本地转发,用户vlan的网关在一台交换机上。交换机可以配置vlanstatistic以统计vlan内的流量。但vlan流量统计后,没有对应的snmpoid,考虑使用python脚本来进行取值。在zabbix......
  • js将后端返回的文件流导出,并自定义下载文件名(pdf导出)
    这里调接口时记得加上responseType:'blob'/***@description:下载文件*@param{string}data文件流*@param{string}filename文件名*@return{*}*/exportfunctiondownloadFile(data:string,filename:string){constblob=newBlob([data])const......
  • Three.js教程:自定义顶点UV坐标
    推荐:将NSDT场景编辑器加入你的3D工具链其他工具集:NSDT简石数字孪生自定义顶点UV坐标学习自定义顶点UV坐标之前,首先保证你对BufferGeometry的顶点数据、纹理贴图都有一定的理解。#顶点UV坐标的作用顶点UV坐标的作用是从纹理贴图上提取像素映射到网格模型Mesh的几何体表面上。浏览器......
  • 使用whoops作为tp6的自定义异常
    安装composerrequirefilp/whoops在app/ExceptionHandle.php中的renderpublicfunctionrender($request,Throwable$e):Response{//添加自定义异常处理机制if(ENV('APP_DEBUG')){//如果是HttpResponseException异常则原样输出//JUMP插......