运行数小时后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
相关产品推荐
相关产品推荐

