文章目录
MyBatis xml sql常用结构记录
sql语句语法
SQL语句中 in 和 exists 的区别
select * from a where a.id in (select b.id from b)
select * from a where exists(select 1 from b where b.id=a.id)
sql的效率在 a,b的大小不同时会得到不同的效果。
分析过程
1.使用in关键词时是先将 b表的数据查询出来置于内存,遍历b表的数据,去查询a表。
假设B有100000条记录,A有10条记录,会交互100000次数据库;再假设B有10条记录,A有100000记录,只会发生10次交互。
2.使用exist关键词时,先将a表数据置于内存,
假设A有10000条记录,B有10条记录,数据库交互次数为10000;假设A有10条,B有10000条,数据库交互次数为10。
3.使用in关键词时,不会应用到索引 ,使用exist进行子查询时 ,可以应用到索引
结论:当主表小于子表时,使用exists,当子表小于主表时,使用in
case when else
此处含义:当AFTERSALES_ORDER_ID=0时 返回 SKU_ORDER_ID
当 AFTERSALES_ORDER_ID !=0时 返回 AFTERSALES_ORDER_ID
若以上两条都不满足 则返回零
(CASE WHEN twt.AFTERSALES_ORDER_ID=0 THEN twt.SKU_ORDER_ID
WHEN twt.AFTERSALES_ORDER_ID!=0 THEN twt.AFTERSALES_ORDER_ID
else 0
end)
as 订单号
多表连接时需要注意
1.查询是否涉及到主表概念,如果存在应该使用left join进行表连接,且需要注意相连接的两张表的数量对应关系(一对一、一对多、多对多),因为如果不是一对一的关系会导致查询结果比主表多出数据。
Mybatis/MybatisPlus基本语法
分页查询
首先根据自己的mybatis-plus版本选择合适的分页插件 mybatis-plus是物理分页 会根据sql拼接limit字段
查询的结构如下
SELECT COUNT(1) FROM TR_WORK_TICKET
SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( select * from TR_WORK_TICKET ) TMP WHERE ROWNUM <=10) WHERE ROW_ID > 0
Page<TrWorkTicketEntity> page=new Page<>(2,10);
List<TrWorkTicketEntity> list=trWorkTicketMapper.selectMethodPage(page);
大于小于符号处理
因为xml是标签语言,当我们的 > <出现的时候可能会出现报错的情况 所以可选择红字的字符进行代替
需要注意的是,转译字符是不能直接当做sql语句去执行的,我们的sql语句还是需要改成真正的 < >符号
判断参数某个属性不为空
<if test="param.mainOrderId !=null and param.mainOrderId != ''">
and tom.MAIN_ORDER_ID=#{param.mainOrderId}
</if>
在进行模糊查询时
此处使用的是 || 符号进行字符串拼接
and twt.TRICKET_CONTENT like '%'|| #{param.tricketContent} ||'%'
choose when 结构
<choose>
<when test="param.ticketType == 1">
and twt.TICKET_TYPE=1
</when>
<when test="param.ticketType == 2">
and twt.TICKET_TYPE=2
</when>
<otherwise>
and twt.TICKET_TYPE=3
</otherwise>
</choose>
include 标签应用
使用include标签时,在执行一个 mapper方法时 会将 <sql> 中的语句拼接到前方的sql语句中进行执行。
select twt.rowid RID
<include refid="workTicket"></include>
<sql id="workTicket">
from TR_WORK_TICKET twt
left join TR_ORDER_MAIN_SKU toms
on twt.sku_order_id = toms.sku_order_id
left join TR_ORDER_MAIN tom
on toms.MAIN_ORDER_ID =tom.MAIN_ORDER_ID
</sql>
开始日期、截止日期
根据前端传入的日期字符串,在后端将日期字符串按照指定格式转化成数据库的date类型进行日期的比较
<if test="param.startTime !=null and param.startTime !='' ">
and twt.CREATE_TIME >=to_date(#{param.startTime},'yyyy-mm-dd')
</if>
<if test="param.endTime!=null and param.endTime !=''">
and twt.CREATE_TIME < to_date(#{param.endTime},'yyyy-mm-dd') + 1
</if>
MyBatis Xml文件if 判断一个值等于另一个值
等于某一个值时,选择了 *.toString 进行判断和选择拼接不同的sql语句 **
<if test="param.orderType !=null">
<if test="param.orderType != null and param.orderType == '1'.toString() ">
and not exists (select * from TR_ORDER_MAIN_SKU oms join GS_GOODS_SKU_MAPPING gsm on oms.SKU_ID=gsm.SKU_ID where oms.MAIN_ORDER_ID=t.MAIN_ORDER_ID )
</if>
<if test="param.orderType != null and param.orderType != '1'.toString() ">
and t.MAIN_ORDER_ID in (select distinct(oms.MAIN_ORDER_ID) from TR_ORDER_MAIN_SKU oms join GS_GOODS_SKU_MAPPING gsm on oms.SKU_ID=gsm.SKU_ID where gsm.GOODS_TYPE=#{param.orderType})
</if>
</if>
oracle 分页查询基础结构
(select RID
from (select R.RID, ROWNUM LINENUM
from (select twt.rowid RID
<include refid="workTicket"></include>
) R
where ROWNUM <= #{param.pageSize} * #{param.pageNum})
where LINENUM > #{param.pageSize} * (#{param.pageNum} - 1)) TAB1
public void mainReflect() {
Object o=new TrWorkTicketEntity();
boolean hasCreateUser = false;
Class<?> aClass = o.getClass();
Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
if(field.getName().equals("createUser")){
hasCreateUser=true;
break;
}
}
if(hasCreateUser){
try {
Method setCreateUser = aClass.getMethod("setCreateUser",String.class);
String userName = "fengyu";
setCreateUser.invoke(o,userName);
System.out.println(o);
} catch (Exception e) {
log.info("切面出现异常");
}
}
}
Mybatis 调用函数
大写处为对应的函数的名称
select F_WORK_TICKET_REST_TIME(to_char(t.expect_time,'yyyy-mm-dd hh24:mi:ss')) as rest_time from TR_WORK_TICKET t
Mybatis 调用数据库存储过程代码示例
// 传入参数是一个 map类型
Map<String, String> map = new HashMap<>();
map.put("v_logistics_id", String.valueOf(param.getLogisticsId()));
map.put("v_content", param.getContent());
map.put("v_logistics_time", param.getLogisticsTime());
trOrderMainMapper.sp_order_logistics_record_save(map);
// 在调用完存储过程之后,可以通过map 参数得到该存储过程的调用返回结果
if (!"success".equalsIgnoreCase(map.get("v_out_code"))) {
throw new BusinessException(CommonResponseCode.ORDER_ERROR.getCode(), map.get("v_out_msg"));
} else {
trOrderLogisticsMapper.updateLogisticsStatus(param.getLogisticsId());
}
-- 通过call关键字调用存储过程 并声明相关的参数和返回结果。
<select id="sp_order_logistics_record_save" statementType="CALLABLE" parameterType="java.util.Map">
{
call sp_order_logistics_record_save(
#{map.v_logistics_id, mode=IN,jdbcType=BIGINT },
#{map.v_content, mode=IN,jdbcType=VARCHAR },
#{map.v_logistics_time, mode=IN,jdbcType=VARCHAR },
#{map.v_out_code,mode=OUT,jdbcType=VARCHAR },
#{map.v_out_msg,mode=OUT,jdbcType=VARCHAR }
)
}
</select>
dual表
因为在 Oracle 中,SELECT 语句必须要有 FROM 子句,所以在某些只需要计算表达式或调用内置函数的情况下,我们需要借助 DUAL 表来保证语法的正确性。
oracle 编写函数简单示例
-- 工单根据期望日期计算剩余时间
create or replace function F_WORK_TICKET_REST_TIME(expext_time_str varchar2)
return varchar2 is
expext_time Date;
restTime varchar2(32);
restTimeNumber number;
restDay number;
restHour number;
restMinute number;
begin
-- 计算得出两日期相差的秒数
-- 1min = 60 s
-- 1hour = 60*60 s
-- 1day = 24*60*60 s
expext_time := To_date(expext_time_str, 'yyyy-mm-dd hh24-mi-ss');
select ceil((expext_time - sysdate) * 24 * 60 * 60)
into restTimeNumber
from dual;
restDay := ABS(ceil(restTimeNumber / (24 * 60 * 60)));
restTimeNumber := MOD(restTimeNumber, 24 * 60 * 60);
restHour := ABS(ceil(restTimeNumber / (60 * 60)));
restTimeNumber := MOD(restTimeNumber, 60 * 60);
restMinute := ABS(ceil(restTimeNumber / 60));
if expext_time > sysdate then
restTime := '剩余' || restDay || '天' || restHour || '小时' || restMinute || '分';
elsif expext_time < sysdate then
restTime := '超时' || restDay || '天' || restHour || '小时' || restMinute || '分';
end if;
return restTime;
end F_WORK_TICKET_REST_TIME;