当前位置: 首页 > news >正文

java对接oracle存储过程基本知识(附Demo)

目录

  • 前言
  • 1. 基本知识
  • 2. Demo
  • 3. 实战

前言

🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF

爬虫神器,无代码爬取,就来:bright.cn

Java基本知识:

  1. java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
  2. 【Java项目】实战CRUD的功能整理(持续更新)

1. 基本知识

Java 通过 JDBC 连接 Oracle 数据库并调用存储过程的方式主要有两种:

  • 使用 CallableStatement 直接调用存储过程(原生 JDBC)

  • 使用 MyBatis 映射存储过程(推荐)

再补充个Sql的基本知识:(sql 参数检查)

查询对应存储过程的输入输出是什么:

SELECT argument_name, data_type, in_out
FROM all_arguments
WHERE object_name = 'xxx'
AND owner = 'YOUR_SCHEMA_NAME';

然后确保 jdbcType 与数据库的参数类型一致,比如:

  • VARCHAR2 → jdbcType=VARCHAR
  • NUMBER → jdbcType=NUMERIC
  • DATE → jdbcType=TIMESTAMP 或 jdbcType=DATE

截图如下:

在这里插入图片描述

2. Demo

需要先引入依赖包,否则会出现如下所示:

java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)

截图如下:

在这里插入图片描述

依赖包如下:

<!--        oracle-->
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>19.8.0.0</version>
</dependency>

不以Mybatis进行解析,纯Demo:

  1. 加载 Oracle JDBC 驱动:
    使用 oracle.jdbc.driver.OracleDriver 进行驱动加载(Spring Boot 可通过 DataSource 自动管理)

  2. 建立数据库连接:
    通过 DriverManager.getConnection() 或数据源 DataSource 连接数据库

  3. 创建 CallableStatement:
    通过 connection.prepareCall("{ call procedure_name(?, ?, ...) }") 创建存储过程调用对象

  4. 绑定输入、输出参数:
    IN 参数:使用 setXXX(index, value) 绑定值
    OUT 参数:使用 registerOutParameter(index, sqlType) 声明输出参数

  5. 执行存储过程:
    使用 callableStatement.execute() 执行存储过程
    通过 getXXX(index) 读取输出参数的返回值

  6. 关闭连接:
    CallableStatement 和 Connection 需要在 finally 块中关闭,避免资源泄露

import java.sql.*;
import java.text.SimpleDateFormat;

public class OracleProcedureCall {
    public static void main(String[] args) {
        String url = "jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=xxxxx)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=xxxx)))";
        String username = "xxx";
        String password = "xxx";

        Connection conn = null;
        CallableStatement cstmt = null;

        try {
            // 1. 加载驱动(JDBC 4.0 及以上可省略)
            Class.forName("oracle.jdbc.driver.OracleDriver");

            // 2. 建立数据库连接
            conn = DriverManager.getConnection(url, username, password);

            // 3. 预编译存储过程,使用命名参数
            String procedureCall = "{ call xxxxxx(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) }";
            cstmt = conn.prepareCall(procedureCall);

            // 4. 设置输入参数
            cstmt.setString("xx1", "1");
            cstmt.setInt("xx2", 2);

            // 处理日期时间
            String dateStr = "2025-03-12 04:31:11"; // 格式:yyyy-MM-dd HH:mm:ss
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            java.util.Date parsedDate = dateFormat.parse(dateStr);
            Timestamp timestamp = new Timestamp(parsedDate.getTime());
            cstmt.setTimestamp("xx3", timestamp);

            cstmt.setString("xx4", "4");
            cstmt.setString("xx5", "5");
            cstmt.setString("xx6", "6");
            cstmt.setString("xx7", "7");

            // 5. 注册输出参数
            cstmt.registerOutParameter("wl_cntr_plac", Types.VARCHAR);
            cstmt.registerOutParameter("wl_new_cntr", Types.VARCHAR);
            cstmt.registerOutParameter("wl_new_cntr_plac", Types.VARCHAR);
            cstmt.registerOutParameter("wl_return", Types.VARCHAR);

            // 6. 执行存储过程
            cstmt.execute();

            // 7. 获取输出参数
            String wl_cntr_plac = cstmt.getString("wl_cntr_plac");
            String wl_new_cntr = cstmt.getString("wl_new_cntr");
            String wl_new_cntr_plac = cstmt.getString("wl_new_cntr_plac");
            String wl_return = cstmt.getString("wl_return");

            System.out.println("wl_cntr_plac: " + wl_cntr_plac);
            System.out.println("wl_new_cntr: " + wl_new_cntr);
            System.out.println("wl_new_cntr_plac: " + wl_new_cntr_plac);
            System.out.println("wl_return: " + wl_return);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 8. 关闭资源
            try {
                if (cstmt != null) cstmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

截图如下:

在这里插入图片描述

如果是Mybaits写法,具体如下:

特意隐藏一些数据,以xx进行代替:

<insert id="callExchangeCntrGateProcedure" statementType="CALLABLE">
    { call xxx(
        #{xx1,mode=IN,jdbcType=VARCHAR},
        #{xx2,mode=IN,jdbcType=NUMERIC},
        #{xx3,mode=IN,jdbcType=DATE},
        #{xx4,mode=IN,jdbcType=VARCHAR},
        #{xx5,mode=IN,jdbcType=VARCHAR},
        #{xx6,mode=IN,jdbcType=VARCHAR},
        #{xx8,mode=OUT,jdbcType=VARCHAR},
        #{xx7,mode=OUT,jdbcType=VARCHAR},
        #{xx9,mode=OUT,jdbcType=VARCHAR},
        #{xx10,mode=IN,jdbcType=VARCHAR},
        #{xx11,mode=OUT,jdbcType=VARCHAR}
    ) }
</insert>

然后在 Mapper 接口 里这样写:

@Mapper
public interface MyMapper {
    void callExchangeCntrGateProcedure(Map<String, Object> params);
}

调用时:

@Autowired
private MyMapper myMapper;

public void executeProcedure() {
    Map<String, Object> params = new HashMap<>();
    params.put("xx1", "E3051486");
    params.put("xx2", 1001);
    params.put("xx3", new Timestamp(System.currentTimeMillis()));
    params.put("xx4", "SLS");
    params.put("xx5", "R");
    params.put("xx6", "G05");
    params.put("xx7", "C1");

    // MyBatis 会自动填充 OUT 参数
    myMapper.callExchangeCntrGateProcedure(params);

    System.out.println("wl_cntr_plac: " + params.get("wl_cntr_plac"));
    System.out.println("wl_new_cntr: " + params.get("wl_new_cntr"));
    System.out.println("wl_new_cntr_plac: " + params.get("wl_new_cntr_plac"));
    System.out.println("wl_return: " + params.get("wl_return"));
}
方法适用场景主要特点
CallableStatement(命名参数)适用于 JDBC 原生代码手动绑定参数,清晰易维护
MyBatis #{} 方式适用于 Spring + MyBatis代码更简洁,自动管理参数

3. 实战

以Demo为基本知识 融合到实战中!

本身需要跨源数据库,所以结合DS注解,该注解可看我之前的文章:详细分析MybatisPLus中@DS切换数据源的基本知识(附Demo)

新建一个基本类,用于跨源数据库

在这里插入图片描述

对应实现类打上DS:

在这里插入图片描述

实际代码如下:

@Resource
private CabinetSwapMapper cabinetSwapMapper;


@Override
@DS("xxx")
public Map<String, Object> callExchangeCntrGate(CabinetSwapDO cabinetSwapDO, String cntrDam) {


    // **调用存储过程**
    Map<String, Object> params = new HashMap<>();
    params.put("xxx", cabinetSwapDO.getOrderId());
 
 	// 省略
    params.put("wlChangRsn", cabinetSwapDO.getDamDes());

    // 执行存储过程
    cabinetSwapMapper.callExchangeCntrGate(params);

    return params;
}

此处的存储过程后续便于对接Mabatis.xml文件:

@Mapper
public interface CabinetSwapMapper extends BaseMapperX<CabinetSwapDO> {

    void callExchangeCntrGate(Map<String, Object> params);
}

注意的关键点如下:

在这里插入图片描述

后续直接调用即可:

Map<String, Object> result = commonGateService.callExchangeCntrGate(cabinetSwapDO, reason);
String xxx= (String) result.get("xxx");

上述代码需要注意IN有什么要传入的,而且参数的字段类型要正确,传输的格式也要正确!

可以先在数据库软件中测试对应的类型:

在这里插入图片描述

相关文章:

  • 设计模式 行为型设计模式
  • 记录关于Unitask的一些基础使用
  • Time spent invoking a CUDA kernel
  • 【Linux】系统文件的权限管理
  • open3d教程 (二)点云的读写
  • 常用天然地震链接
  • 【JAVA】十、基础知识“类和对象”干货分享~(一)
  • 香港理工视觉语言模型赋能智能制造最新综述!基于视觉语言模型的人机协作在智能制造中的应用
  • secure keyboard entry is enabled because another app has turned it on.
  • 阿里通义千问发布全模态开源大模型Qwen2.5-Omni-7B
  • 鸿蒙阔折叠Pura X外屏开发适配
  • MySQL的备份及还原
  • C++多线程的性能优化
  • 怎样配置windows云主机不关闭显示器
  • 小程序中跨页面组件共享数据的实现方法与对比
  • platform总线驱动简单示例
  • 探索新一代大模型代理(LLM agent)及其架构
  • AI Agent创新10大前沿方向与落地实践分析
  • 如何使用CUDA Graphs,如何更新Graphs中kernel函数参数
  • 利用 Chrome devTools Source Override 实现JS逆向破解案例
  • 德国放弃长期以来的反核立场,寻求修复德法合作关系
  • 国家发改委:进一步完善促进民营经济发展的制度机制
  • 李在明遭遇暗杀威胁,韩国警方锁定两名嫌疑人
  • 山西晋城一网红徒步野游线路据传发生驴友坠崖,当地已宣布封路
  • 4天内,云南昆明又一县市区原主官被查
  • 交响4K修复版《神女》昨晚上演,观众听到了阮玲玉的声音