目录
项目创建
使用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路径(这里没有配置过,所以为空),请求映射路径 /
当然不能忘了请求的参数,结合程序数据需求,加上合适的参数;
接口支持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数据库的存储过程演示结束,希望对读者有帮助!