Mybatis如何传递多个参数——一个莫名空指针错误引起的思考

Posted dongxiaoxuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis如何传递多个参数——一个莫名空指针错误引起的思考相关的知识,希望对你有一定的参考价值。

一、前言

今天在做一些高并发的简单测试时(主要测试悲观锁、乐观锁、重入机制等等的效率,加深对锁的理解),报了一个莫名其妙的空指针错误:

技术分享图片

错误原因指向一个业务实现类,于是赶忙打开该类查看第62行代码:

 

技术分享图片

观察到,第62行只是一个简单的判断语句:

if(redPacket.getStock() > 0)

该判断句所引对象来自61行代码:

RedPacket redPacket = redPacketDAO.getRedPacket(redPacketId);

思考后发现,如果是空指针错误的话,那应该是对象redPacket为空,也就是说61行代码执行失败了。问题来了:既然61行执行失败,干嘛要报62行的错?果然,在我注释掉62行及以后的代码,print打印redPacket对象时,发现该对象本身及其所有属性均能正常打印(自动该类调用自定义的toString()方法),并没有报错。

 

哈,到这里真的有点摸不着头脑了,对象和他的属性均正常,set.get方法也无误,一个线程它正儿八经,正正常常的一行一行执行着,前一句不空,后一句突然变空,这…………

 

困难是有的,但还是可以解决的!抱着试一试的心态,先把62行外层if语句里所有内容注释掉,尝试性又执行一遍,额,空指针没了。

以上就是发现这个奇葩空指针源头的过程,再之后就简单了,一句句排查,锁定了错误的源头在Mybatis的这个方法中:

技术分享图片

 我注意到,sql语句中,参数有两个:id和version,我却还当作一个参数来处理:没有定义parameterType。粗心的毛病啊,,,,当时这段是直接复制悲观锁的代码,根本没注意到多加了一个参数。

二、Mybatis如何传递多个参数

四种方法噢,咱由浅入深,先从最不常用的开始,哈哈。

(1)采用Map传多参数。

    Dao层:

public int selectUser(Map paramMap);

    Mapper.xml:

<update id="selectUser">
        update table_name
        set xxx
        where id = #{id}
        and version = #{version}
 </update>

    Service层:

Private User x(){
    Map paramMap=new hashMap();
    paramMap.put(“id”,”2”);
    paramMap.put(“version”,”1”);
    User user=xxx. selectUser(paramMap);
}

(2)使用#{arg0},#{arg1}...或#{param1},#{param2}

细心的小伙伴遇到类似错误时可能会发现错误日志里有类似的提醒:

Parameter ‘id’ not found. Available parameters are [arg1, arg0, param1, param2] 

没错,就是把sql代码中#{id}和#{version}改为#{arg0}或者#{param1}等等:(注意:arg下标从0开始,param下标从1开始

    Dao层:

public int selectUser(Long id, int version);

    Mapper.xml:

<update id="selectUser">
        update table_name
        set xxx
        where id = #{arg0}
        and version = #{arg1}
 </update>

(3)定义一个实体类来承载多个参数

    pojo(实体类):

public class Param(){
private Long id; private int version; -------getter and setter------- }

    DAO层:

public int selectUser(Param p);

    Mapper.xml:同(1)

(4)使用@Param注解

    DAO层:

public int selectUser(@Param("id") Long id, @Param("version") int version);

    Mapper.xml同(1)

 

这四种方法中,个人认为第四种方法最好,使用@Param注解能让开发者看到dao层方法就知道该传什么样的参数,比较直观。

选择上述四种方法任意一种,问题解决。

三、结语

与其说问题已经解决,不如说只是代码不报错了而已。留给我的问题是:为嘛参数传递格式有问题,会报空指针错误?为嘛对象正常,只有调用属性的getter方法才会报错?仍在思考,希望路过的大神指导一二。

 


以上是关于Mybatis如何传递多个参数——一个莫名空指针错误引起的思考的主要内容,如果未能解决你的问题,请参考以下文章

mybatis执行insert方法向数据库插入数据时,报空指针求

MyBatis:Mybatis 参数传递用法

mybatis 入参传多个list

Mybatis (ParameterType) 如何传递多个不同类型的参数

spring boot继承web和mybatis时,调用接口删除记录出现的空指针以及解决办法

mybatis传递多个参数值(转)