You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行数小时后MyBatis与JDBC查询均返回Null但数据库存在数据

问题描述

系统运行数小时后,通过MyBatis查询mapi_session表的指定数据返回Null;使用原生JDBC执行相同查询也返回Null,但数据库中确实存在对应数据。已尝试将BaseDataSource替换为ComboPooledDataSource,问题仍未解决。

MyBatis查询代码

<select id="selectMapiSession" parameterType="long" resultMap="mapiSessionMap">
    SELECT 
        mapi_session_id,
        scr_id,
        mapi_user_id,
        session_description,
        session_start_date,
        session_end_date,
        effective_date,
        expiration_date,
        mapi_repository_id
    FROM mapi_session
    WHERE mapi_session_id = #{mapiSessionID}
</select>

JDBC查询代码

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Object bean = context.getBean("sqlSessionFactoryMAPI");

SqlSessionFactory ses=(SqlSessionFactory) bean;
DAO_RoutingDataSource dataSource = (DAO_RoutingDataSource) ses.getConfiguration().getEnvironment().getDataSource();

String sql = "SELECT mapi_session_id scr_id,"
        + "         mapi_user_id,"
        + "         session_description,"
        + "         session_start_date,"
        + "         session_end_date,"
        + "         effective_date,"
        + "         expiration_date,"
        + "         mapi_repository_id"
        + "     FROM mapi_session"
        + "        WHERE mapi_session_id = ?";

HashMap<String, Object> resultMap = new HashMap<>();

try (Connection connection = dataSource.getConnection();
     PreparedStatement statement = connection.prepareStatement(sql)) 
{

    statement.setLong(1, Long.valueOf(mapiSessionId.toString()));
    
    try (ResultSet resultSet = statement.executeQuery())
    {
        if (resultSet.next()) 
        {
            resultMap.put("scr_id", resultSet.getLong("scr_id"));
            resultMap.put("mapi_user_id", resultSet.getLong("mapi_user_id"));
            resultMap.put("session_description", resultSet.getString("session_description"));
            resultMap.put("session_start_date", resultSet.getDate("session_start_date"));
            resultMap.put("session_end_date", resultSet.getDate("session_end_date"));
            resultMap.put("effective_date", resultSet.getDate("effective_date"));
            resultMap.put("expiration_date", resultSet.getDate("expiration_date"));
            resultMap.put("mapi_repository_id", resultSet.getLong("mapi_repository_id"));
        }
    }
    catch (SQLException e) 
    {
        logger.error("< Fetching mapi session forcefully is not working >", e);
        throw e;
    }
}

if(resultMap!=null && !resultMap.isEmpty()) 
{
    return resultMap;
}
return null;

MyBatis配置文件

<!--        <setting name="lazyLoadingEnabled" value="false"/>  -->

<setting name="lazyLoadingEnabled" value="true"/>  
<setting name="aggressiveLazyLoading" value="false"/>  
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>  
<!-- <setting name="proxyFactory" value="CGLIB"/> -->
<!-- <setting name="multipleResultSetsEnabled" value="true"/> -->
<!-- <setting name="useColumnLabel" value="true"/> -->
<!-- <setting name="useGeneratedKeys" value="false"/> -->
<!-- <setting name="defaultStatementTimeout" value="25000"/> -->
<!-- <setting name="safeRowBoundsEnabled" value="false"/> -->
<!-- <setting name="localCacheScope" value="SESSION"/> -->
<!-- <setting name="jdbcTypeForNull" value="OTHER"/> -->
</settings>

<typeAliases>
    <package
        name="com.oneshield.tools.dataaccess, com.oneshield.tools.domain, com.oneshield.tools.dto" />
</typeAliases>

共用DataSource配置

<bean id="baseDataSource" class="org.apache.commons.dbcp.BasicDataSource"
    abstract="true" scope="singleton" destroy-method="close">

    <property name="initialSize" value="0" /> <!-- 初始连接数:池启动时创建的连接数量,默认0 -->

    <property name="maxActive" value="10" /> <!-- 最大活跃连接数:同时可分配的最大连接数,默认8,负数表示无限制 -->
                                            
    <property name="maxIdle" value="8" /> <!-- 最大空闲连接数:池中保持空闲的最大连接数,默认8,负数表示无限制 -->
                                            
    <property name="minIdle" value="0" /> <!-- 最小空闲连接数:池中保持空闲的最小连接数,默认0 -->
                                            
    <property name="maxWait" value="-1" /> <!-- 最大等待时间:无可用连接时的等待毫秒数,-1表示无限等待 -->
                                                    
    <property name="testOnBorrow" value="true" /> <!-- 借连接时验证:从池取连接前验证有效性,失效则丢弃并尝试取新连接,默认true -->
                                                    
    <property name="validationQuery" value="SELECT 1 FROM DUAL" /> <!-- 验证查询:用于验证连接的SQL,必须是返回至少一行的SELECT语句 -->
                                                                    
    <property name="connectionInitSqls" value="ALTER SESSION SET NLS_SORT=BINARY_CI" /> <!-- 连接初始化SQL:物理连接创建时执行的SQL,仅执行一次 -->

    <property name="timeBetweenEvictionRunsMillis" value="300000" /> <!-- 空闲连接清理线程间隔:清理线程运行间隔毫秒数,非正数不启动线程 -->

    <property name="minEvictableIdleTimeMillis" value="1800000" /> <!-- 最小空闲回收时间:连接空闲超过该时间则被回收,默认30分钟 -->
                                                                        
    <property name="removeAbandoned" value="true" /> <!-- 移除废弃连接:开启后会在清理周期移除废弃连接,需配合timeBetweenEvictionRunsMillis使用 -->
                                                                
    <property name="removeAbandonedTimeout" value="300" /> <!-- 废弃连接超时:连接超过该时间未使用则标记为废弃,默认300秒 -->
</bean>

排查方向

  • 数据库路由/一致性问题:检查DAO_RoutingDataSource是否路由到错误数据库实例(如主从库同步延迟),直接在应用服务器上用数据库客户端执行相同SQL,对比结果。
  • 连接池会话状态异常:SELECT 1 FROM DUAL仅验证连接存活,无法保证会话配置有效。可修改validationQuery加入会话校验(如SELECT SYS_CONTEXT('USERENV','NLS_SORT') FROM DUAL),确认ALTER SESSION配置在连接复用后依然生效;部分连接池归还连接时会重置会话,需检查相关配置。
  • 参数与字段映射问题:打印实际执行的SQL和参数值,确认mapiSessionId转换为Long后与数据库中mapi_session_id的类型/值完全匹配;JDBC查询中把mapi_session_id别名为scr_id,需确认数据库中该字段类型与getLong兼容。
  • MyBatis缓存问题:尝试设置localCacheScope=STATEMENT禁用会话级缓存,或每次查询使用新的SqlSession,排查是否命中旧缓存。

内容的提问来源于stack exchange,提问作者Harsimarpreet singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:37:31