0
点赞
收藏
分享

微信扫一扫

mybatis大坑

坑一:distinct失效

注意看,小明写了一段简单的sql用distinct去重,直接执行完全没有问题。

select distinct a.oid,a.goods_wh_code,c.goods_name,a.settlement_amt,a.settlement_status,
a.receipt_time as settlementTime,c.goods_alloy,pb.brand_name,pg.oid AS goodOid,spv.contacts_phone
from sc_settlement_dt a
left join wm_tmp_codes wtc on wtc.goods_wh_code = a.goods_wh_code
left join sc_po_goods spg on wtc.tmp_wh_code = spg.tmp_wh_code
left join sc_purchase_order spo on spo.oid = spg.po_oid
left join sc_po_vendor spv on spv.oid=spo.po_ven_oid
left join sc_settlement b on a.parent_oid = b.oid
left join wm_wh_goods_info c on c.goods_wh_code = a.goods_wh_code
left join sc_vendor d on a.ven_code = d.ven_code
left join ( SELECT goods_wh_code, create_time FROM wm_entry_dt GROUP BY goods_wh_code,
create_time ) wet ON wet.goods_wh_code = c.goods_wh_code
left join (select ven_oid, contacts_phone
from sc_vendor_contacts
where ven_oid =
(select ven_oid from sc_vendor_contacts where contacts_phone =#{dto.loginPhone})) svc on svc.ven_oid = d.oid
left join pd_goods pg on pg.goods_code = c.goods_code
left join pd_brand pb on pg.goods_brand_code = pb.brand_code
<where>
    svc.contacts_phone is not null and a.settlement_status != 'O' and a.settlement_status != 'W'
    <if test="dto.settlementStatus!=null">
        <if test="dto.settlementStatus == 1">and a.settlement_status = 'P'
        </if>
        <if test="dto.settlementStatus == 0">
            and a.settlement_status = 'S'
        </if>
    </if>
 </where

>

但用了mybatis,分页导致解析时变成了下面这样

原因分析:因为distinct只能用于修饰第一个字段,而分页时第一个字段是伪列,根据oid去重就失效了。真坑啊,测了半天sql没问题,还是需要测解析后最终执行的sql

SELECT COUNT(*) FROM (SELECT DISTINCT a.oid, a.goods_wh_code, c.goods_name, a.settlement_amt, a.settlement_status, a.receipt_time AS settlementTime, c.goods_alloy, pb.brand_name, pg.oid AS goodOid, spv.contacts_phone FROM sc_settlement_dt a LEFT JOIN wm_tmp_codes wtc ON wtc.goods_wh_code = a.goods_wh_code LEFT JOIN sc_po_goods spg ON wtc.tmp_wh_code = spg.tmp_wh_code LEFT JOIN sc_purchase_order spo ON spo.oid = spg.po_oid LEFT JOIN sc_po_vendor spv ON spv.oid = spo.po_ven_oid LEFT JOIN sc_settlement b ON a.parent_oid = b.oid LEFT JOIN wm_wh_goods_info c ON c.goods_wh_code = a.goods_wh_code LEFT JOIN sc_vendor d ON a.ven_code = d.ven_code LEFT JOIN (SELECT goods_wh_code, create_time FROM wm_entry_dt GROUP BY goods_wh_code, create_time) wet ON wet.goods_wh_code = c.goods_wh_code LEFT JOIN (SELECT ven_oid, contacts_phone FROM sc_vendor_contacts WHERE ven_oid = (SELECT ven_oid FROM sc_vendor_contacts WHERE contacts_phone = '15242868250')) svc ON svc.ven_oid = d.oid LEFT JOIN pd_goods pg ON pg.goods_code = c.goods_code LEFT JOIN pd_brand pb ON pg.goods_brand_code = pb.brand_code WHERE svc.contacts_phone IS NOT NULL AND a.settlement_status != 'O' AND a.settlement_status != 'W' AND a.settlement_status = 'P' AND spv.contacts_phone IN ('18816471221')) TOTAL;


SELECT DISTINCT TOP
	100 PERCENT ROW_NUMBER ( ) OVER ( ORDER BY CURRENT_TIMESTAMP ) AS __row_number__,
	a.oid,
	a.goods_wh_code,
	c.goods_name,
	a.settlement_amt,
	a.settlement_status,
	a.receipt_time AS settlementTime,
	c.goods_alloy,
	pb.brand_name,
	pg.oid AS goodOid,
	spv.contacts_phone 
FROM
	sc_settlement_dt a
	LEFT JOIN wm_tmp_codes wtc ON wtc.goods_wh_code = a.goods_wh_code
	LEFT JOIN sc_po_goods spg ON wtc.tmp_wh_code = spg.tmp_wh_code
	LEFT JOIN sc_purchase_order spo ON spo.oid = spg.po_oid
	LEFT JOIN sc_po_vendor spv ON spv.oid= spo.po_ven_oid
	LEFT JOIN sc_settlement b ON a.parent_oid = b.oid
	LEFT JOIN wm_wh_goods_info c ON c.goods_wh_code = a.goods_wh_code
	LEFT JOIN sc_vendor d ON a.ven_code = d.ven_code
	LEFT JOIN ( SELECT goods_wh_code, create_time FROM wm_entry_dt GROUP BY goods_wh_code, create_time ) wet ON wet.goods_wh_code = c.goods_wh_code
	LEFT JOIN ( SELECT ven_oid, contacts_phone FROM sc_vendor_contacts WHERE ven_oid = ( SELECT ven_oid FROM sc_vendor_contacts WHERE contacts_phone = '15242868250' ) ) svc ON svc.ven_oid = d.oid
	LEFT JOIN pd_goods pg ON pg.goods_code = c.goods_code
	LEFT JOIN pd_brand pb ON pg.goods_brand_code = pb.brand_code 
WHERE
	svc.contacts_phone IS NOT NULL 
	AND a.settlement_status != 'O' 
	AND a.settlement_status != 'W' 
	AND a.settlement_status = 'P' 
	AND spv.contacts_phone IN ( '18816471221' )

解决方案:

在sql外面套一层select t.* from()t,绑死这对cp,但要记得把order by 提出来,子查询里面不可以有排序的。

坑二,使用mybatis进行整型字段过滤,整型字段传值为0时,过滤失效

看这段sql,本来判断 是基操,

但是settlementStatus==0时,settlementStatus==其他值的数据也查了出来

<select id="wxShopSettlementList" resultType="com.juxi.system.api.domain.wm.vo.WxSettlementVO">
    select t.* from (select distinct a.oid,a.goods_wh_code,c.goods_name,a.settlement_amt,a.settlement_status,
    a.receipt_time as settlementTime,c.goods_alloy,pb.brand_name,pg.oid AS goodOid,spv.contacts_phone
    from sc_settlement_dt a
    left join wm_tmp_codes wtc on wtc.goods_wh_code = a.goods_wh_code
    left join sc_po_goods spg on wtc.tmp_wh_code = spg.tmp_wh_code
    left join sc_purchase_order spo on spo.oid = spg.po_oid
    left join sc_po_vendor spv on spv.oid=spo.po_ven_oid
    left join sc_settlement b on a.parent_oid = b.oid
    left join wm_wh_goods_info c on c.goods_wh_code = a.goods_wh_code
    left join sc_vendor d on a.ven_code = d.ven_code
    left join ( SELECT goods_wh_code, create_time FROM wm_entry_dt GROUP BY goods_wh_code,
    create_time ) wet ON wet.goods_wh_code = c.goods_wh_code
    left join (select ven_oid, contacts_phone
    from sc_vendor_contacts
    where ven_oid =
    (select ven_oid from sc_vendor_contacts where contacts_phone =#{dto.loginPhone})) svc on svc.ven_oid = d.oid
    left join pd_goods pg on pg.goods_code = c.goods_code
    left join pd_brand pb on pg.goods_brand_code = pb.brand_code
    <where>
        svc.contacts_phone is not null and a.settlement_status != 'O' and a.settlement_status != 'W'
        <if test="dto.settlementStatus!=null and settlementStatus!= ''">
            <if test="dto.settlementStatus == 1">and a.settlement_status = 'P'
            </if>
            <if test="dto.settlementStatus == 0">
                and a.settlement_status = 'S'
            </if>
        </if>
        )t
</select>

原因分析:

        深入mybatis源码中解析IfSqlNode类可以看出,最终进行比较空串和0值的逻辑在Ognl.isEqual方法中如下图所示:

 最终比较的是在Ognl.compareWithConversion方法中,会将被比较的空字符串和传入的参数值0都转换为double类型, 然后进行比较:

因为status=0是Integer类型,其父类是Number类型,所以这里0也会转换为0.0;

上面的判断结果最终导致status=0的过滤条件被忽略

解决方案:

        在if标签的test判断条件中去掉dto.status != ''的条件即可,服了

<if test="dto.settlementStatus!=null">
    <if test="dto.settlementStatus == 1">
        and a.settlement_status = 'P'
    </if>
    <if test="dto.settlementStatus == 0">
        and a.settlement_status = 'S'
    </if>
</if>

举报

相关推荐

0 条评论