1.问题复现
(1) 原有一处老的查询业务,循环列表然后依次查询数据库内容,插入到列表对象中展示,先不说遗留代码的查询性能问题;出现了展示的列表中对象数据重复问题; (2) 伪代码:
for(EntityList entity: entitys){
//数据库中查询商品信息
Integer goodsId = entity.getGoodsId();
GoodsInfo goodsInfo = goodsMapper.queryById(goodsId);
//列表对象中保存有不同的描述信息,并赋值到商品信息对象
String desc = entity.getDesc();
goodsInfo.setDesc(desc);
//将商品信息对象赋值到列表对象
entity.setGoodsInfo(goodsInfo);
}
(3)出现数据重复错误原因: 由于该方法开启了事务@Transactional.导致mybatis默认开启了一级session级别缓存LocalCache,所以在同一session中,查询相同的sql返回的是缓存的同一个对象; 所以,当 goodsMapper.queryById(goodsId)查询的goodsId相同时,除了第一次,后面都是执行的查询缓存,所以返回的 GoodsInfo goodsInfo 是同一个,导致了后面赋值不同desc会被最后一个所覆盖,列表不同对象entity.setGoodsInfo(goodsInfo)也即是同一个GoodsInfo对象;
2.解决问题
(1)改进业务代码,避免出现类似的循环查询相同sql导致缓存的问题; (2)设置一级缓存,statement级别的缓存每一次查询后清除; session级别缓存在同一个SqlSession的insert、update、delete操作之前清除
@Bean
public SqlSessionFactoryBean wfSqlSessionFactoryBeanPro(@Qualifier("dataSource") DataSource datasource) {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
bean.setTypeAliasesPackage("com.wfcm.entity");
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setLogImpl(NoLoggingImpl.class);// 不输出日志()
// configuration.setLogImpl(WfStdOutImpl.class);//标准输出日志
configuration.setMapUnderscoreToCamelCase(true);// 开启驼峰命名
configuration.setCallSettersOnNulls(true);// 开启在属性为null也调用setter方法
configuration.setDefaultStatementTimeout(180);//默认超时
configuration.setLocalCacheScope(LocalCacheScope.STATEMENT);
bean.setConfiguration(configuration);
return bean;
}
本文由 GY 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2022/12/29 14:32