Rumah >Java >javaTutorial >Apakah cache tahap pertama Java Mybatis dan cache tahap kedua?
Cache ialah kawasan dalam memori yang menyimpan data Tujuannya adalah untuk meningkatkan kecekapan pertanyaan. MyBatis akan menyimpan hasil pertanyaan dalam cache Apabila melaksanakan SQL yang sama pada masa akan datang, pangkalan data tidak akan diakses, tetapi hasilnya akan diperoleh terus daripada cache , sekali gus mengurangkan tekanan pada pelayan.
Apakah cache?
Sekeping data yang wujud dalam ingatan.
Apakah peranan cache?
Kurangkan interaksi antara program dan pangkalan data, tingkatkan kecekapan pertanyaan dan kurangkan tekanan pada pelayan dan pangkalan data.
Apakah jenis data yang dicache?
Data yang kerap ditanya tetapi tidak kerap ditukar, dan perubahan akan memberi sedikit kesan kepada keputusan.
Apakah kategori cache MyBatis?
Cache peringkat pertama dan cache peringkat kedua
Bagaimana untuk menilai sama ada dua Sql adalah sama?
Pernyataan Sql bagi pertanyaan adalah sama, nilai parameter yang dilalui adalah sama, keperluan untuk set hasil adalah sama, ID templat yang telah disusun sebelumnya adalah sama
MyBatis Cache peringkat pertama juga dipanggil cache tempatan. Objek SqlSession mengandungi objek Executor, dan objek Executor mengandungi objek PerpetualCache, yang menyimpan data cache peringkat pertama.
Memandangkan cache peringkat pertama berada dalam objek SqlSession, cache peringkat pertama hanya boleh dikongsi apabila menggunakan objek SqlSession yang sama untuk mengendalikan pangkalan data.
Cache peringkat pertama MyBatis didayakan secara lalai dan tidak memerlukan sebarang konfigurasi.
Seperti yang ditunjukkan di bawah:
Malah, kaedah ujian adalah sangat mudah, iaitu, dengan menggunakan objek SqlSession yang sama dan berbeza untuk melakukan pertanyaan SQL, anda boleh mengetahui sama ada nilai cincang objek yang dikembalikan adalah sama Jika nilai cincang dipulangkan adalah sama, ini bermakna pertanyaan SQL tidak dilakukan, tetapi secara langsung Dapatkan objek dari cache dan kembalikan
Yang berikut menggunakan objek Sesi yang sama untuk melaksanakan pertanyaan . Jika nilai cincang pengguna1 dan pengguna2 adalah sama, ini bermakna cache tahap pertama memang didayakan, dan Tiada pertanyaan, tetapi data diambil terus dari cache.
import com.mybatisstudy.mapper.UserMapper; import com.mybatisstudy.pojo.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.InputStream; public class TestUserMapper3 { // 测试使用同一个SqlSession查询 @Test public void testCache1() throws Exception{ InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); SqlSession session = factory.openSession(); // 使用同一个SqlSession查询 UserMapper mapper1 = session.getMapper(UserMapper.class); UserMapper mapper2 = session.getMapper(UserMapper.class); User user1 = mapper1.findById(1); System.out.println(user1.hashCode()); System.out.println("------------------------------------------"); User user2 = mapper2.findById(1); System.out.println(user2.hashCode()); session.close(); } }
Hasil pelaksanaan
OK, sesungguhnya nilai hash yang dikembalikan adalah sama , dan kami boleh menunjukkan melalui output konsol bahawa ia tidak membuat pertanyaan tetapi secara langsung mendapatkan objek daripada cache dan mengembalikannya, jadi ini ialah cache peringkat pertama, yang meningkatkan kecekapan pertanyaan.
Sekarang gunakan SqlSession yang berbeza untuk menguji sama ada nilai cincang yang dikembalikan adalah konsisten
// 测试使用不同SqlSession查询 @Test public void testCache2() throws Exception{ InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); SqlSession session1 = factory.openSession(); SqlSession session2 = factory.openSession(); // 测试使用不同SqlSession查询 UserMapper mapper1 = session1.getMapper(UserMapper.class); UserMapper mapper2 = session2.getMapper(UserMapper.class); User user1 = mapper1.findById(1); System.out.println(user1.hashCode()); System.out.println("---------------------------------"); User user2 = mapper2.findById(1); System.out.println(user2.hashCode()); session1.close(); session2.close(); }
Jalankan hasil
OK, anda dapat melihat bahawa nilai cincang yang dikembalikan adalah berbeza, dan anda juga boleh melihat daripada output konsol bahawa pertanyaan memang dilakukan di sini, jadi ia boleh disahkan, Cache peringkat pertama yang dikongsi sememangnya berdasarkan objek SqlSession
Tetapi, jika terdapat terlalu banyak cache, ia juga akan memberi kesan Pertanyaan kami adalah cekap, jadi kami perlu mengosongkan cache pada masa ini, sama seperti kami perlu mengosongkan cache telefon mudah alih dari semasa ke semasa jika tidak, ia akan menjadi sangat tersekat . Jadi bagaimana untuk mengosongkan cache peringkat pertama?
Lakukan operasi berikut untuk mengosongkan cache peringkat pertama MyBatis:
Panggilan SqlSession close(): Selepas operasi, objek SqlSession tidak tersedia dan data Cached objek juga tidak tersedia.
SqlSession memanggil clearCache() / commit(): operasi akan mengosongkan data cache peringkat pertama.
SqlSession memanggil kaedah penambahan, pemadaman dan pengubahsuaian: operasi akan mengosongkan data cache peringkat pertama, kerana pangkalan data berubah selepas penambahan, pemadaman dan pengubahsuaian, data cache akan menjadi tidak tepat
// 清空Mybatis一级缓存 @Test public void testCache3() throws Exception{ InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); SqlSession session = factory.openSession(); UserMapper mapper1 = session.getMapper(UserMapper.class); UserMapper mapper2 = session.getMapper(UserMapper.class); User user1 = mapper1.findById(1); System.out.println(user1.hashCode()); // 清空Mybatis一级缓存 session.clearCache(); System.out.println("-------------------------------"); User user2 = mapper2.findById(1); System.out.println(user2.hashCode()); session.close(); }
Kesan pelaksanaan
OK, nilai cincang yang dikembalikan memang berbeza, tetapi pernahkah kita perhatikan Apabila menggunakan objek SqlSession yang berbeza untuk melaksanakan pertanyaan di sini, paparan input konsol adalah sedikit berbeza Iaitu, tidak perlu mewujudkan sambungan JDBC di sini, yang juga meningkatkan kecekapan pertanyaan dengan berkesan. jadi kita masih perlu mengosongkan cache sekali-sekala
MyBatis二级缓存也叫全局缓存。数据存放在SqlSessionFactory中,只要是同一个工厂对象创建的SqlSession,在进行查询时都能共享数据。一般在项目中只有一个SqlSessionFactory对象,所以二级缓存的数据是全项目共享的。
MyBatis一级缓存存放的是对象,二级缓存存放的是对象的数据。所以要求二级缓存存放的POJO必须是可序列化的,也就是要实现Serializable接口。
MyBatis二级缓存默认不开启,手动开启后数据先存放在一级缓存中,只有一级缓存数据清空后,数据才会存到二级缓存中。
SqlSession 调用 clearCache() 无法将数据存到二级缓存中。
1. POJO类实现Serializable接口
import java.io.Serializable; public class User implements Serializable { private int id; private String username; private String sex; private String address; }
2. 在Mybatis配置文件添加如下设置
<!-- 二级缓存打开 --> <settings> <setting></setting> </settings>
这里有个额外知识,就是Mybatis配置文件的标签还得按照顺序来放的,否则就会以下编译错误;
The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,
objectWrapperFactory?,reflectorFactory?,plugins?,environments?,
databaseIdProvider?,mappers?)".
同时也说明了放置顺序就得按照match里面的顺序来放
3. 添加
如果查询到的集合中对象过多,二级缓存只能缓存1024个对象引用。可以通过
标签的size属性修改该数量。 比如:
那怎么测试呢,从上面我们可以知道二级缓存存放的是对象的数据,并且是基于SqlSessionFactory的,因此我们可以用SqlSessionFactory获取两个SqlSession对象,然后让他们分别获取各自的mapper,然后进行查询,返回到同一个实例化的USer对象中,如果返回的数据是一致的,但是对象的哈希值是不一样的话,则说明二级缓存里存放的确实对象的数据而不是对象。
// 测试二级缓存 @Test public void testCache4() throws Exception { InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); SqlSession session = factory.openSession(); UserMapper mapper1 = session.getMapper(UserMapper.class); UserMapper mapper2 = session.getMapper(UserMapper.class); User user1 = mapper1.findById(1); System.out.println(user1); System.out.println(user1.hashCode()); // 让一级缓存失效 session.commit(); System.out.println("----------------------------"); user1 = mapper2.findById(1); System.out.println(user1); System.out.println(user1.hashCode()); }
运行结果
OK,从运行结果上我们可以知道结果集返回到同一个对象中,而他们的哈希值反而不一样,说明执行第二次查询的时候新建了一个对象并且该对象指向那个对象并且将SqlSessionFactory中的数据赋值到新建的那个对象。其实从控制台打印的日志我们也可以得出,并没有执行查询方法,因为没有打印SQL语句,而且缓存也是从0.0改成了0.5,因此我们可以断定二级缓存存放的是数据而不是对象。
Atas ialah kandungan terperinci Apakah cache tahap pertama Java Mybatis dan cache tahap kedua?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!