Mybatis Plus 调用Oracle存储 返回索引 Cursor
什么要写这篇博客
mybatis 调用oracle 存储过程,返回一个表。这样的景场用得比较少,我用了mybatis这么长时间,还第一次这么用。
尝试过程也是比较痛苦,网上资料少不说,很多配置拿下来,也是跑不起来。。最后自己不停地跟据mybatis抛出来的错误,调整代码,终于跑起来了。做一下笔记。
存储过程
存储过程比较长,只需要关注输入,输出参数就可以了。
CREATE OR REPLACE PROCEDURE P_QMS_GET_MIS_RPT(MIS_TYPE VARCHAR2, --1:3MIS 2:6MIS
MIS_DATE VARCHAR2, --时间条件
OTHER_CONDITION VARCHAR2, --其它条件
DATE_TYPE NVARCHAR2, -- 1:年 2:月 3:周
GROUP_BY VARCHAR2, --维度 BRAND
P_CUR OUT SYS_REFCURSOR
) AS
V_SQL VARCHAR2(4000);
V_CON VARCHAR2(500):='';
V_DATE DATE;
V_STRAT_DATE date;
V_END_DATE date;
V_MIS_MONTH varchar2(50);
V_START_DATE_STR VARCHAR2(100);
V_END_DATE_STR VARCHAR2(100);
BEGIN
V_DATE:=TO_DATE(MIS_DATE,'yyyy-MM-dd');
V_STRAT_DATE := Trunc(add_months(V_DATE, -3 * MIS_TYPE ), 'mm');
V_END_DATE := Last_Day(add_months(V_DATE, -1));
V_MIS_MONTH := to_char(Trunc(add_months(V_DATE, -1), 'mm'), 'yyyymm');
V_START_DATE_STR:= ' to_date('''|| to_char( V_STRAT_DATE,'yyyy-MM-dd') ||''',''yyyy-MM-dd'') ';
V_END_DATE_STR := ' to_date('''|| to_char( V_END_DATE,'yyyy-MM-dd') ||''',''yyyy-MM-dd'') ';
V_CON:=V_CON || ' and ACTIVE_START>= ' || V_START_DATE_STR ;
V_CON:=V_CON || ' and ACTIVE_START < '|| V_END_DATE_STR || '+1';
V_CON:=V_CON|| ' ';
V_SQL := ' with B as --市场不良数
(SELECT '|| GROUP_BY ||', sum(QTY) AS sc_qty
FROM T_QMS_DB_COMMON_CACULATE cc
where cc.CACULATE_TYPE = ''10''
'|| V_CON ||'
group by '|| GROUP_BY ||'),
--销售数量
C as
(SELECT '|| GROUP_BY ||', sum(QTY) AS s_qty
FROM T_QMS_DB_COMMON_CACULATE cc
where cc.CACULATE_TYPE = ''40''
'|| V_CON ||'
group by '|| GROUP_BY ||' ),
--生产数量
D as
(SELECT '|| GROUP_BY ||', sum(QTY) AS pro_qty
FROM T_QMS_DB_COMMON_CACULATE cc
where cc.CACULATE_TYPE = ''30''
'|| V_CON ||'
group by '|| GROUP_BY ||' ),
--销售比率
E as
(select d.'|| GROUP_BY ||',
round(least(sum(c.s_qty) / sum(d.pro_qty), 1), 8) as rate,
sum(c.s_qty) sale_qty,
sum(d.pro_qty) pro_qty
from D, c
where 1 = 1 and
d.'|| GROUP_BY ||' = c.'|| GROUP_BY ||'
group by d.'|| GROUP_BY ||'),
--交货数量
F as
(SELECT '|| GROUP_BY ||', sum(QTY) AS part_qty
FROM T_QMS_DB_COMMON_CACULATE cc
where cc.CACULATE_TYPE = ''20''
'|| V_CON ||'
group by '|| GROUP_BY ||' ),
--交货数量*销售比率获取 =索赔零件总数
G as
(select F.BRAND, sum(F.part_qty * E.rate) as instrorage_qty
from F, E
where F.'|| GROUP_BY ||' = E.'|| GROUP_BY ||'
group by F.'|| GROUP_BY ||'),
--计算实绩值
H AS
(select G.'|| GROUP_BY ||',
B.sc_qty,
instrorage_qty,
round(B.sc_qty / instrorage_qty * 1000000, 1) as rate,
round(B.sc_qty / instrorage_qty * 1000000, 10) rate_dec
from G
left join B
on G.'|| GROUP_BY ||' = B.'|| GROUP_BY ||'),
V AS
(SELECT TARGET_VAL, BRAND AS TARGET_TYPE_NAME
FROM T_QMS_DB_TARGET_VAL T
WHERE
T.BUSI_TYPE = ''10''
AND T.TARGET_DATE= '''||V_MIS_MONTH||''')
SELECT
'|| GROUP_BY ||' as SUMARY_NAME,
rate_dec,
'''||V_MIS_MONTH||''' as MIS_DATE,
nvl((select target_val from V where H.'|| GROUP_BY ||' = V.target_type_name and rownum=1), 0) as target_val
FROM H';
OPEN P_CUR FOR V_SQL;
END;
Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.xx.xx.xx.reportstatic.idal.mapper.MisRptMapper">
<resultMap id= "misPrcInputResult" type ="com.ly.mp.qms.reportstatic.entities.MisPrcInputResult" >
<result column ="sumary_name" property="sumaryName" jdbcType="VARCHAR" />
<result column ="rate" property="rate" jdbcType="VARCHAR" />
<result column ="mis_date" property="misDate" jdbcType="VARCHAR" />
<result column ="target_val" property="targetVal" jdbcType="VARCHAR" />
</resultMap >
<select id="getMisRpt" statementType="CALLABLE" >
{call p_qms_get_mis_rpt
(
#{misType,mode=IN,jdbcType=VARCHAR}, <!--注意要使用置jdbcType -->
#{misDate,mode=IN,jdbcType=VARCHAR},
#{otherCondition,mode=IN,jdbcType=VARCHAR},
#{dateType,mode=IN,jdbcType=VARCHAR},
#{groupBy,mode=IN,jdbcType=VARCHAR},
#{result,mode=OUT,jdbcType=CURSOR, javaType=ResultSet,resultMap=misPrcInputResult}
)}
</select>
</mapper>
这里主要注意
1:输入参数的格式为 #{misType,mode=IN,jdbcType=VARCHAR},需要设参数名称(misType),参数类型 (mode=IN),参数数据类型(jdbcType=VARCHAR)为字符,网上找的资料都是没有设置 jdbcType=VARCHAR,但我的环境跑不起来。
2:输出参数设置, #{result,mode=OUT,jdbcType=CURSOR, javaType=ResultSet,resultMap=misPrcInputResult。名称(result),参数类型为输出(mode=OUT),参数数据类型(jdbcType=CURSOR)为索引。
输出的参数还需要另外设置javaType和resultMap。javaType=ResultSet 表示对应的java类型是一个列表,对应List;resultMap=misPrcInputResult 表示集合字段对应的印身是 misPrcInputResult。
Entity
public class MisPrcInputResult implements java.io.Serializable
{
private String sumaryName;
private String rate;
private String misDate;
private String targetVal;
public String getSumaryName() {
return sumaryName;
}
public void setSumaryName(String sumaryName) {
this.sumaryName = sumaryName;
}
public String getRate() {
return rate;
}
public void setRate(String rate) {
this.rate = rate;
}
public String getMisDate() {
return misDate;
}
public void setMisDate(String misDate) {
this.misDate = misDate;
}
public String getTargetVal() {
return targetVal;
}
public void setTargetVal(String targetVal) {
this.targetVal = targetVal;
}
}
import java.sql.Date;
import java.util.List;
public class MisPrcInput implements java.io.Serializable {
private String misType;
private String misDate;
private String otherCondition;
private String dateType;
private String groupBy;
private List<MisPrcInputResult> result;
public String getMisType() {
return misType;
}
public void setMisType(String misType) {
this.misType = misType;
}
public String getMisDate() {
return misDate;
}
public void setMisDate(String misDate) {
this.misDate = misDate;
}
public String getOtherCondition() {
return otherCondition;
}
public void setOtherCondition(String otherCondition) {
this.otherCondition = otherCondition;
}
public String getDateType() {
return dateType;
}
public void setDateType(String dateType) {
this.dateType = dateType;
}
public String getGroupBy() {
return groupBy;
}
public void setGroupBy(String groupBy) {
this.groupBy = groupBy;
}
public List<MisPrcInputResult> getResult() {
return result;
}
public void setResult(List<MisPrcInputResult> result) {
this.result = result;
}
}
Mapper.java
public interface MisRptMapper extends BaseMapper<MisCaculate> {
public void getMisRpt(MisPrcInput inp );
}
Biz
@Autowired
MisRptMapper misRptMapper;
@Override
public RestResult<List<MisPrcInputResult>> getMisPrc() throws ParseException {
MisPrcInput inp= new MisPrcInput();
inp.setDateType("1");
inp.setGroupBy("brand");
inp.setMisType("1");
inp.setMisDate("2018-02-1");
inp.setOtherCondition( " 1=1 ");
inp.setResult(new ArrayList<MisPrcInputResult>());
RestResult<List<MisPrcInputResult>> result =new RestResult();
result.setResult(1);
misRptMapper.getMisRpt( inp);
result.setMsg("获取成功");
result.setData(inp.getResult());
return result;
}
接口跟Service层就不贴代码了。。
最终运行结果