使用注解的方式调用Oracle数据库的存储过程;

目录

项目创建

项目整体结构

存储过程

配置项目

返回结果类型

*编写dao层[本篇博客关键]

service实现层

控制层

测试接口并除错


项目创建

使用spring官方的初始化工具spring initializr(网址为https://start.spring.io/)创建一个springboot项目

(使用IDE工具也可进行创建,只不过用可能在下载依赖时出错),

并自行添加所需的依赖。如图1-1所示。

                                                                图1-1

接着将创建好的项目(大小仅几十KB)下载下来进行解压,使用集成开发工具IDEA打开。使用构建工具maven下载所需的依赖。

本次演示所用到的依赖如下所示:


	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.7.16</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.jhzy</groupId>
	<artifactId>proName</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>proName</name>
	<description>这里写对项目的描述</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>


	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.3.1</version>
		</dependency>

		<dependency>
			<groupId>com.oracle.database.jdbc</groupId>
			<artifactId>ojdbc8</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter-test</artifactId>
			<version>2.3.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

下载好项目所需的依赖之后,修改application.properties为application.yml

(后缀为yml的文件配置是以键值对形式,更加简洁)并打开进行项目的基本配置。

项目整体结构

        文件项目目录和文件如下图1-2所示:

        

                                                        图1-2

存储过程

存储过程如图1-3所示(请读者根据自己项目的实际需求进行编写。这里只是进行存储过程示意)

                                                    图1-3

配置项目

如下,在application.yml文件中进行配置:

# 配置Oracle数据库的数据源;
spring:
  datasource:
    driver-class-name: oracle.jdbc.driver.OracleDriver
    url: jdbc:oracle:thin:@localhost:1521:orcl
    username: dyhs
    password: 1

# 设置项目端口号为80。浏览器默认的端口号是80,这样访问服务时可不写端口号;
server:
  port: 80

# 设置mybatis执行的sql在控制台中打印,便于观察sql的执行情况;
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  # 让 mybatis 找到mapper目录中的 xml 文件
  mapper-locations: classpath:mapper/*.xml

首先明确我们需要的返回结果是什么样的类型,所以编码的顺序有讲究。

编写顺序依次为:实体bean,dao层,service实现层,service抽象层,controller控制层;

响应此请求的顺序恰好相反,从控制层开始;

当然,如果业务较为复杂,我们可以在编写完实体bean之后,先在xml文件中写sql,再写dao层;

在resources目录下创建mapper文件夹,然后在mapper文件夹下创建对应的如AssetsMapper.xml文件,写复杂的SQL;

注意创建文件要遵循springboot的默认规则;

返回结果类型

准备调用存储过程返回类型的实体类bean;

package com.jhzy.proName.entity;

import lombok.Data;
import lombok.experimental.Accessors;

@Data // lombok的注解,省略了getter和setter,使代码更简洁;
@Accessors(chain = true) // lombok的注解,对象可以链式调用调用属性;
public class ViewBalanceSheet1 {
    // 入参
    private String GSDM;
    private String ZTH;
    private String KJND;
    private String KJQJ;
    // 出参
    private String gsmc; // 公司名称
    private String B5;
    private String C5;
    private String B6;
    private String C6; // 为了节省篇幅和便于阅读理解,以下省略了将近200个出参...
}

*编写dao层[本篇博客关键]

编写调用存储过程的dao层;

package com.jhzy.proName.dao;

import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.StatementType;

import java.util.Map;

@Mapper
public interface AssetsDao {
    // 表示调用存储过程;
    @Options(statementType = StatementType.CALLABLE)
    /*
    调用存储过程,并传参(包括出参[这里定义出参为Res]和入参);
    注意映射的 resultMap 值 assetsResult 和注解 @Results 的 id 对应绑定;
    */
    @Select("call balance_report(#{gsdm_in},#{zth_in},#{kjnd_in},#{kjqj_in}," +
            "#{Res,mode=OUT,jdbcType=CURSOR,resultMap=assetsResult})")
    /*
当实体类属性名和数据表字段名不一样时,这样写让个别几个不一样的实体类属性和数据表字段相互对应;
若两者已经完全对应了,则不需要在value里面再次编写 @Result 去对应了,让其为空就好;
     */
    @Results(id = "assetsResult", value = {
        //  @Result(column = "B5", property = "B5"),
        //  @Result(column = "C5", property = "C5"),
        //  @Result(column = "B6", property = "B6")
    })
    /*
     @ResultType 注解见名知意,表示声明返回结果的类型;
     */
    @ResultType(com.jhzy.proName.entity.ViewBalanceSheet1.class)
    /*
     这里很特别,入参和出参都使用map来传递;这与我们平时只用来传递入参有区别;
     也就是说,查询出来的结果也使用参数 Map 来返回;
     */
    void callBalanceSheet(Map map);
}

此时没有非常复杂的逻辑,所以不编写抽象service,直接编写service实现;

service实现层

直接编写service层;

package com.jhzy.proName.service;

import com.jhzy.proName.dao.AssetsDao;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;

@Service
public class AssetsService {
    @Resource
    AssetsDao assetsDao; // 注入AssetsDao;
   
    // 注意这里的返回类型是void,返回空;因为返回的结果已经放到 Map 中;
    public void assetsList(Map map) {
        // 调用dao层
        assetsDao.callBalanceSheet(map); 
    }
}

控制层

最后一步编写Controller;

package com.jhzy.proName.controller;


import com.jhzy.proName.entity.ViewBalanceSheet1;
import com.jhzy.proName.service.AssetsService;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class Controller {

    @Resource
    AssetsService assetsService; // 注入AssetsService;

    @GetMapping("/") // 访问路径;
    @CrossOrigin // 使用这个注解表示请求可以跨域;
    public List<ViewBalanceSheet1> assetsList(String gsdm, String zth,
                                              String kjnd, String kjqj) {
        Map map = new HashMap();
        map.put("gsdm_in",gsdm);
        map.put("zth_in",zth);
        map.put("kjnd_in",kjnd);
        map.put("kjqj_in",kjqj); // 入参放入map中进行传递;
        assetsService.assetsList(map); // 放入参数 map,调用service;
        // 使用map获取返回的结果,并强转为 ViewBalanceSheet1 的 List 类型;
        List<ViewBalanceSheet1> columns = (List)map.get("Res");
        return columns;
    }
}

测试接口并除错

code完成,测试接口是否有bug;如果用错误,则需根据对应的错误提示进行调试,除错;

按照此例的端口号80,上下文contex路径(这里没有配置过,所以为空),请求映射路径 / 

当然不能忘了请求的参数,结合程序数据需求,加上合适的参数;

所以URL应为:"http://localhost/?gsdm=01002002&zth=002&kjnd=2023&kjqj=10icon-default.png?t=N7T8http://localhost/?gsdm=01002002&zth=002&kjnd=2023&kjqj=10

接口支持get请求,所以可以直接使用浏览器测试;

使用Google浏览器测试结果如下:

程序出现异常,报500错误;需要查看后端报错提示进行排错,提示信息如下:

uncategorized SQLException; SQL state [99999]; 
error code [17056]; 
不支持的字符集 (在类路径中添加 orai18n.jar): ZHS16GBK; 
nested exception is java.sql.SQLException: 
不支持的字符集 (在类路径中添加 orai18n.jar): ZHS16GBK] with root cause

java.sql.SQLException: 不支持的字符集 (在类路径中添加 orai18n.jar): ZHS16GBK

观察错误信息可以知道,是SQL错误,不支持字符集ZHS16GBK;

且此处给出了解决方法:(在类路径中添加 orai18n.jar);需要添加依赖;

网上查阅可知需要在项目中添加依赖:

		<dependency>
			<groupId>com.oracle.database.nls</groupId>
			<artifactId>orai18n</artifactId>
			<version>19.7.0.0</version>
		</dependency>

加载依赖重启项目,再次测试接口,结果如下:


​​​​​​结果正确!至此,调用Oracle数据库的存储过程演示结束,希望对读者有帮助!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值