【java】Mybatis返回int类型为空时报错 attempted to return null from a method with a primitive return type (int)

本文解决了一个Mybatis框架中由于返回null值引发的异常问题,通过将返回类型从int更改为Integer避免了错误。同时,深入探讨了Java中int和Integer的区别,包括初始化、存储方式及使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言
在往常敲代码的时候没有留意过int和Integer的区别,今天在敲代码的时候,ORM框架使用的是Mybatis,一个简单的查询,返回查询的条数。当查询为null的时候,就报错了。

二、报的错误
试图从具有原始返回类型(int)的方法返回null

org.apache.ibatis.binding.BindingException: Mapper method 'com.dmsdbj.itoo.basicInfo.dao.RoomDao.selectSumCountCapacity attempted to return null from a method with a primitive return type (int).

    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:93)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
    at com.sun.proxy.$Proxy35.selectSumCountCapacity(Unknown Source)
    at com.dmsdbj.itoo.basicInfo.service.impl.PlaceManageServiceImpl.selectSumCountCapacity(PlaceManageServiceImpl.java:858)
    at com.dmsdbj.itoo.basicInfo.service.impl.PlaceManageServiceImpl$$FastClassBySpringCGLIB$$c31f6b08.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:669)
    at com.dmsdbj.itoo.basicInfo.service.impl.PlaceManageServiceImpl$$EnhancerBySpringCGLIB$$49d6b6e3.selectSumCountCapacity(<generated>)
    at com.dmsdbj.itoo.basicInfo.facade.impl.PlaceManageFacadeImpl.selectSumCountCapacity(PlaceManageFacadeImpl.java:439)
    at com.dmsdbj.itoo.basicInfo.facade.test.PlaceManageFacadeTest.testselectSumCountCapacity_false(PlaceManageFacadeTest.java:342)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)

三、解决方案
Mybatis的mapper文件的返回类型resultType为Integer:
返回类型设置为封装类型Integer而不是基本类型int。

<!--查询未安排考场的教室总容量-王雷-2017年9月1日15:09:25-->
    <select id="selectSumCountCapacity"  resultType="Integer">
        SELECT
        IFNULL( SUM(room_capacity),0)
        FROM
        t_room
        <if test="roomTypeId !=null">
        WHERE
        roomType_id = #{roomTypeId}
        </if>
        <if test="roomIds !=null and roomIds.size()>0">
        AND id NOT IN (

            <foreach collection="roomIds" item="item" separator=",">
                #{item}
            </foreach>

        )
        </if>
    </select>

Service之间的返回值也是Ingeger:

/**
     * 查询未安排考场的教室总容量-王雷-2017年9月1日15:09:25
     * @param roomIds
     * @param roomTypeId
     * @return
     */
    public Integer selectSumCountCapacity(List<String> roomIds ,String roomTypeId){
        if (roomIds==null||roomTypeId==""){
            logger.debug("查询未安排考场的教室总容量,已使用的房间id为空,将查询所有的房间容量");
        }

        return roomDao.selectSumCountCapacity(roomIds, roomTypeId);
    }

另外:若遇到该问题,可使用MySQL的IFNULL函数和MAX函数,将返回的NULL值转换为0。例如,可将上述SQL语句改为:

SELECT IFFULL(MAX(name),0) AS name FROM user WHERE id = #{id}

四、int和integer的区别
以前一直没有思考,为啥要有一个int还要有一个integer。实际上:

  • 1.Ingeter是int的包装类,int的初值为0,Ingeter的初值为null;

  • 2.初始化的时候,int i =1;Integer i= new Integer(1);(要把integer 当做一个类看);但由于有了自动装箱和拆箱使得对Integer类也可使用:Integer i= 1;

  • 3.int 是基本数据类型(面向过程留下的痕迹,不过是对java的有益补充),Integer 是一个类,是int的扩展,定义了很多的转换方法

  • 4.Integer是对象,用一个引用指向这个对象,而int是基本类型,直接存储数值。

五、小结
java中的数据类型分为基本数据类型和复杂数据类型,int是基本数据类型,integer是复杂数据类型,复杂基本类型也就是一个类,所以初始化为null。

从基本知识出发,能更加夯实自己的基础。

<think>好的,我现在需要解决用户遇到的MyBatis Mapper方法返回null给基本类型int的问题。用户提供的错误信息是Mapper方法试图返回null,但方法返回类型是基本类型int,导致异常。我需要先理解这个问题的原因,然后找到解决方案。 首先,回忆一下MyBatis的工作原理。当Mapper接口的方法声明为返回基本类型(如intMyBatis期望数据库操作返回一个结果,并将其转换为对应的基本类型。如果数据库查询的结果是null,而方法返回类型intMyBatis无法将null赋值给int,因为基本类型不能为null。这就会抛出异常,如用户提到的错误信息。 接下来,我需要考虑可能的解决方法。常见的解决方案可能有几种: 1. 修改Mapper方法返回类型为包装类型Integer。这样,如果查询结果为null,可以返回null,而不会出现类型不匹配的问题。但需要检查调用该方法的地方是否接受Integer类型,或者是否需要拆箱处理。 2. 在SQL查询中使用COALESCE或IFNULL函数,确保即使查询结果为null,也会返回一个默认值(如0),从而避免返回null。例如,将SQL语句中的字段改为COALESCE(column, 0),这样结果就不会是null。 3. 在MyBatis的配置文件中设置全局的配置,使得当结果为null自动转换为默认值。但我不太确定MyBatis是否有这样的配置,可能需要进一步查阅文档。 4. 在XML映射文件中使用结果映射(resultMap)或者通过select语句的resultType进行处理,设置默认值。例如,在查询语句中直接处理可能的null值。 现在需要评估这些方法的可行性。第一种方法修改返回类型Integer是直接的解决方案,但可能需要修改接口和调用代码。第二种方法在SQL中处理,不涉及代码修改,可能更简单。第三种方法如果存在的话,可能更方便,但需要确认配置项是否存在。第四种方法类似第二种,可能需要调整SQL语句。 根据用户提供的具体Mapper方法querySumDayNum,假设对应的SQL语句可能是这样的: SELECT SUM(day_num) FROM table WHERE ...; 如果查询结果为,SUM会返回null。这,使用COALESCE(SUM(day_num), 0)可以确保返回0而不是null。这样即使没有符合条件的记录,返回的结果也是0,对应int类型就不会出错了。 同,用户可能需要检查Mapper接口的返回类型是否正确。例如,如果方法声明为int querySumDayNum(...),而查询可能返回null,就会导致错误。将其改为Integer可能也是一种解决方式,但需要确认调用方是否能够处理Integer类型,或者是否有自动拆箱的情况。如果调用方期望基本类型,可能更推荐在SQL中处理null值,返回0。 另外,检查MyBatis的日志或错误信息,确认具体是哪一行代码或哪个SQL语句导致的问题,可以更精准地定位问题点。 总结起来,主要的解决方案有两种:修改返回类型为包装类型,或者在SQL查询中处理null值。根据具体情况选择最适合的方法。对于用户当前的例子,可能更推荐在SQL中使用COALESCE函数,这样无需修改Java代码,只需调整SQL语句即可解决问题。</think>### MyBatis Mapper方法返回null导致基本类型int异常的解决方案 当MyBatis的Mapper接口方法声明为返回基本类型(如`int`),但实际查询结果为`null`,会触发`Mapper method attempted to return null from a method with a primitive return type`异常。以下是具体分析及解决方案: --- #### **原因分析** 1. **基本类型null的冲突** 基本类型(如`int`)不能为`null`,而数据库查询结果可能为`null`(例如聚合函数`SUM()`在无数据返回`null`)。此MyBatis无法将`null`赋值给`int`,导致异常[^1][^2][^3][^4]。 --- #### **解决方案** 根据场景选择以下方法之一: ##### **方法1:修改Mapper接口返回类型为包装类** 将返回类型从`int`改为`Integer`,允许接收`null`值: ```java // 原方法 int querySumDayNum(); // 修改后 Integer querySumDayNum(); ``` - **优点**:简单直接,符合Java类型规范。 - **缺点**:需检查调用方是否兼容`Integer`类型(例如自动拆箱可能引发`NullPointerException`)。 --- ##### **方法2:在SQL查询中处理null值** 使用数据库函数(如`COALESCE`或`IFNULL`)为查询结果提供默认值: ```sql SELECT COALESCE(SUM(day_num), 0) FROM table WHERE ...; -- 或(MySQL) SELECT IFNULL(SUM(day_num), 0) FROM table WHERE ...; ``` - **优点**:无需修改Java代码,结果始终为`0`或其他默认值,兼容`int`类型。 - **缺点**:需调整所有可能返回`null`的SQL语句。 --- ##### **方法3:全局配置MyBatis默认值(不推荐)** 在`mybatis-config.xml`中设置`jdbcTypeForNull`为`OTHER`(需数据库驱动支持): ```xml <settings> <setting name="jdbcTypeForNull" value="OTHER"/> </settings> ``` - **注意**:此方法依赖数据库驱动对`null`值的处理,可能不适用于所有场景。 --- #### **验证示例** 假设Mapper方法为`querySumDayNum`,对应的SQL修改为: ```sql SELECT COALESCE(SUM(day_num), 0) AS total FROM month_free_present WHERE user_id = #{userId}; ``` - 即使无匹配数据,`SUM(day_num)`也会返回`0`,避免`null`值。 --- #### **扩展建议** - **日志调试**:启用MyBatis的SQL日志,确认查询是否返回`null`[^1]。 - **单元测试**:覆盖无数据场景,验证返回值的处理逻辑。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值