import com.study.mybatis.config.SpringConfig;
import com.study.mybatis.entity.Country;
import com.study.mybatis.mapper.CountryMapper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Zhang B H
* @create 2023-10-04 15:40
*/
@ActiveProfiles("qa")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class CacheTest {
@Autowired
private SqlSessionFactory sqlSessionFactory;
/**
* 测试 MyBatis 的一级缓存作用机制
*/
@Test
public void testL1Cache() {
Country country1 = null;
// 获取 sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);
// 获取id为1的国家
country1 = countryMapper.selectByPrimaryKey(1);
// 修改获取到的对象的name实例字段
country1.setName("NEW NAME");
// 再次获取id相同的国家
// 因为 一级缓存 的原因,因此此行代码并不会执行sql查询
Country country2 = countryMapper.selectByPrimaryKey(1);
// 此时,命中一级缓存
Assert.assertEquals(country1, country2);
} finally {
sqlSession.close();
}
sqlSession = sqlSessionFactory.openSession();
try {
CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);
Country country2 = countryMapper.selectByPrimaryKey(1);
Assert.assertNotEquals("NEW NAME", country2.getName());
Assert.assertNotEquals(country1, country2);
// 执行删除操作
// 此时,会清除一级缓存
countryMapper.deleteByPrimaryKey(100);
Country country3 = countryMapper.selectByPrimaryKey(1);
Assert.assertNotEquals(country3, country2);
} finally {
sqlSession.close();
}
}
}
在第一次执行 selectByPrimaryKey 方法获取 Country 时,真正执行了数据库查询,得到了 country1 的结果。而在第二次执行获取 country2 的时候,并没有执行数据库操作。
在关闭第一个 SqlSession 后,又重新获取了一个 SqlSession,然后重新获取了 country2。country2 是一个新的实例,和 country1 没有任何关系。这是因为一级缓存是和 SqlSession 绑定的,只存在于 SqlSession 的生命周期中。
接下来执行了一个 deleteByPrimaryKey 操作,然后使用相同的方法和参数获取了 country3。country3 和 country2 是完全不同的两个对象。这是因为任何的 INSERT、UPDATE、DELETE 操作都会清空一级缓存,所以查询 country3 的时候由于缓存不存在,就会再次执行数据库查询获取数据。