前段时间开发过程中碰到了因为mybatis一级缓存导致对象被重复添加到list的问题,在此记录一下
参考博客:https://www.cnblogs.com/happyflyingpig/p/7739749.html
https://blog.csdn.net/j7636579/article/details/73647885
因为mybatis一级缓存导致对象被重复添加到list
对象A--约束条件,
对象B--需要查询出的对象
Date date = new Date();
List<A> as = new ArrayList<A>();
A a = new A();
a.setDate(date);
a.setProductId(1);
....
A a1 = new A();
a1.setDate(date);
a1.setProductId(1);
....
as.add(a);//a和a1的属性一致
as.add(a1);
List<B> result = new ArrayList<B>();
int i = 0;
for(A a : as) {
//对象A的属性查询B的约束条件,呈现的sql select * from B where date< a.date and productId = a.productId; B date= Bservice.selectB(a);//由于两次查询条件一致,若开启一级缓存,会导致第二次查询返回的是第一次的结果集,对象引用也和第一次一致
//第一次返回 B ={id=1,name=2,...,count=1} date.setCount(i++);//对查出的对象属性赋值 result .add(date); } //result 输出后 [{id=1,name=2,...,count=2},{id=1,name=2,...,count=2}]
Class A{ Date date; int productId; ..... } Class B{ int id; String name; Date date; int productId;
int count; ..... }
开启一级缓存后,查询条件不变,sqlSession 不变,查询返回的结果集也不变,导致了两次查出的对象是同一个
关闭一级缓存,自己尝试了不少方法包括在mapper文件中配置 flushCache="true" useCache="false" ,springboot配置关闭一级缓存---都无效
还有就是调用SqlSession.clearCache(),这种自己没有尝试过
直接在整合mybatis的代码中设置LocalCacheScope属性
@Component @Configuration public class MmsMybatisConfig { //注入WmfDataSourceConfig中配置的ComboPooledDataSource是c2p0的实现标准 @Autowired private DataSource dataSource; private static Logger logger = LoggerFactory.getLogger (MmsMybatisConfig.class);
@Bean(name = "sqlSessionFactory.cms") public SqlSessionFactoryBean sqlSessionFactoryBeanGwcmp() { SqlSessionFactoryBean bean = new SqlSessionFactoryBean (); bean.setDataSource (dataSource); /** * 关闭一级缓存 */ org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setLocalCacheScope(LocalCacheScope.STATEMENT); bean.setConfiguration(configuration); /** * <array> * </array> */ PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver (); String[] path = new String[] {"classpath*:mapper/*.xml","classpath*:com/aspire/boc/settle/*dao/*mapper/*.xml"}; List<Resource> arrayList = new ArrayList<> (); try { for (String s : path ) { List<Resource> asList = Arrays.asList (resolver.getResources (s)); arrayList.addAll (asList); } } catch (IOException e ) { throw new RuntimeException (e); } bean.setMapperLocations (arrayList.toArray (new Resource[arrayList.size ()])); try { logger.info ("bean creat success Mapper [{}]",arrayList.size ()); return bean; } catch (Exception e ) { logger.info ("bean creat error!"); e.printStackTrace (); throw new RuntimeException (e); } }
}