Penelitian dalam artikel ini terutama berfokus pada mekanisme cache hibernasi, sebagai berikut.
Student.java:
Siswa kelas publik {/*ID Siswa*/Private Int ID;/*Nama Siswa*/Nama String Privat;/*Hubungan antara Siswa dan Kelas*/Kelas Kelas Privat; // Hilangkan Metode Setter dan Getter}Class.java:
Kelas Kelas Publik {/*ID Kelas*/Private Int ID;/*Nama kelas*/Nama String Privat;/*Hubungan antara kelas dan siswa*/set privat <siswa> Siswa; // oloskan metode setter dan getter}Student.hbm.xml:
<? XML Versi = "1.0"?> <! Doctype Hibernate-Mapping Public "-// Hibernate/Hibernate Mapping DTD 3.0 // EN" "http://hibernate.sourceForge.net/hibernate-papping-3.0.dtd"> <hibernate-package = "com." com. "com." " TABLE = "t_student"> <id name = "id"> <generator // id> <!-peta properti normal-> <properti name = "name"/> <!-pemetaan banyak-ke-satu, tambahkan kunci asing ke beberapa ujung-> <banyak-ke-satu nama = "class" column = "classid"/</class> </hibernate-papping> colum
Class.hbm.xml:
<? XML Versi = "1.0"?> <! Doctype Hibernate-Mapping Public "-// Hibernate/Hibernate Mapping DTD 3.0 // EN" "http://hibernate.sourceForge.net/hibernate-papping-3.0.dtd"> <hibernate-pack package = "com." com. name="Classes" table="t_classes" lazy="false"> <id name="id"> <generator/generator/> </id> <property name="name"/> <!-- One-to-many mapping, inverse="true" means to hand over the relationship to the peer--> <set name="students" inverse="true"> <key column="classesid"/> <one-to-many/> </set> </belas> </hibernate-Mapping>
Periode deklarasi cache tingkat pertama sangat singkat dan siklus hidup sesi ini konsisten. Cache tingkat pertama juga disebut cache tingkat sesi atau cache tingkat benda. Cache tingkat pertama adalah objek cache dan tidak dapat melakukan cache atribut.
Metode Uji (Gunakan kueri LOAD () dua kali di sesi yang sama):
/*Setelah mengeluarkannya, itu akan ditempatkan di cache, dan kedua kalinya mengambilnya akan langsung diambil dari cache*/ siswa Siswa = (siswa) sesi. System.out.println ("Student.Name =" + Student.getName ()); /*Tidak ada pernyataan kueri yang dikeluarkan, Load menggunakan cache*/ student = (siswa) sesi. System.out.println ("Student.Name =" + Student.getName ());Catatan: Kami akan menemukan bahwa ketika kami pertama kali kueri, hasil yang ditemukan akan ditempatkan di Sesi, Cache, dan Cache Level One. Ketika saya mendapatkan nilai dalam waktu setelah beban () kedua kalinya, saya tidak mengeluarkan pernyataan untuk menanyakannya dalam database, tetapi secara langsung mengambil nilai dari cache (harus dalam sesi yang sama).
Metode Uji Dua (dalam sesi yang sama):
Siswa Siswa = Siswa Baru (); Student.setname ("Zhang San"); Serializable ID = session.save (siswa); Siswa = (Siswa) sesi. // Pernyataan kueri tidak akan dikeluarkan karena Simpan mendukung cache System.out.println ("Student.name =" + Student.getName ());Catatan: Metode Simpan () dipanggil dan dimuat () digunakan untuk memuat objek, dan kemudian atribut nama sebenarnya diperoleh, tetapi tidak ada pernyataan yang dikeluarkan untuk menanyakan database. Karena metode save () juga mendukung cache.
Uji penambahan batch besar data:
public void testCache7 () {session session = null; coba {session = hibernateutils.getSession (); session.begintransaction (); untuk (int i = 0; i <100; i ++) {siswa siswa = siswa baru (); Student.setname ("Zhang San" + i); session.save (siswa); // Perbarui setiap 20 item jika (i % 20 == 0) {// hapus cache, dan setelah memanggil flush, data akan disimpan ke database session.flush (); // Bersihkan sesi konten yang di -cache.clear (); }} session.getTransaction (). commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). rollback (); } akhirnya {hibernateutils.closesession (sesi); }} Catatan:
1. Karena metode save () mendukung cache, ada masalah. Jika saya ingin menghemat 10 juta data pada saat yang sama, maka ada 10 juta objek cache dalam cache, yang kemungkinan akan menyebabkan overflow. Oleh karena itu, Hibernate tidak mendukung operasi pembaruan data skala besar, tetapi kami juga dapat menangani masalah ini dengan sangat fleksibel, seperti membersihkan cache setiap 20 lembar data menggunakan loop.
2. Simpan, perbarui, saveorupdate, muat, dapatkan, daftar, iterate, metode kunci akan menempatkan objek di cache tingkat pertama. Cache tingkat pertama tidak dapat mengontrol jumlah cache, jadi Anda harus memperhatikan kemungkinan meluap memori saat mengoperasikan data dalam batch besar; Anda dapat menggunakan metode penggusuran dan jelas untuk menghapus konten dalam cache.
Cache sekunder juga disebut cache tingkat proses atau cache tingkat sesi, dan cache sekunder dapat dibagikan oleh semua cache sesi. Siklus hidup cache sekunder adalah sama dengan sesiFactory. SessionFactory dapat mengelola cache sekunder. Prinsip cache sekunder digunakan saat membaca jauh lebih besar daripada menulis. Cache sekunder terutama digunakan untuk cache objek entitas.
1. Salin file ehcahe.xml ke direktori src.
2. Tambahkan penyedia produk cache ke file hibernate.cfg.xml, sebagai berikut:
<nama properti = "hibernate.cache.provider_class"> org.hibernate.cache.ehcacheProvider </propert>
3. Aktifkan cache Level 2 (tidak dapat menampilkan startup, karena default diaktifkan), sebagai berikut:
<nama properti = "hibernate.cache.use_second_level_cache"> true </preate>
4. Tentukan kelas entitas mana yang menggunakan cache Level 2.
5. Impor Paket Jar Antarmuka yang Digunakan oleh Cache: lib/optional/ehcache/ehcache-core-2.4.3.jar
Isi file ehcache.xml:
<defaultcache maxeLementsInmemory = "10000" Eternal = "false" timeToidleseconds = "120" timetoliveseconds = "120" overflowTodisk = "true" />
Catatan:
1.MaxElementsInmemory mewakili objek yang paling tersimpan dalam cache.
2.Enernal menunjukkan apakah itu tidak akan pernah kedaluwarsa (mengaturnya menjadi false lebih praktis. Jika benar, itu tidak akan pernah kedaluwarsa, maka atribut berikut tidak ada artinya).
3. Timetoidlesecods menunjukkan berapa lama suatu objek belum diakses setelah pertama kali dibersihkan.
4. TimeTolivesEcods mewakili waktu inventaris suatu objek.
5. OverflowTodisk adalah benar, yang berarti bahwa angka dalam cache melebihi angka yang ditentukan oleh MaxElementsInmemory dan disimpan pada disk.
Tentukan jalur disk yang disimpan pada overflow:
<diskstore path = "java.io.tmpdir"/>
Catatan: Jalur ini dapat diubah.
Metode Uji (premis cache Level 1 adalah harus dalam sesi yang sama. Sekarang kita menggunakan cache Level 2 untuk melihat apakah ada cache dalam dua sesi yang berbeda):
public void testCache1 () {session session = null; coba {session = hibernateutils.getSession (); session.begintransaction (); student student = (student) session.load (student.class, 1); System.out.println ("Student.name =" + student.getName (); Sesi); get. {E.PrintStackTrace (); session.getTransaction (). Rollback ();} akhirnya {hibernateutils.closession (sesi);} coba {sesi = hibernateutils.getSession (); Sesi, dan Configured caChery karena Student = tidak ada caCryery (Student) caChery (Student. Dapat berbagi data dalam cache sekunder {Hibernateutils.closesession (sesi);}}Catatan: Jika cache sekunder dikonfigurasi, kami akan menemukan bahwa bahkan jika sesi pertama ditutup, dan sesi lain dihidupkan untuk memuat data, itu tidak akan mengeluarkan pernyataan untuk meminta data dalam database, karena cache sekunder dikonfigurasi, dibagikan oleh seluruh sesiFactory.
Nonaktifkan cache Level 2 untuk mengimplementasikan penambahan batch besar data:
public void testCache5 () {session session = null; coba {session = hibernateutils.getSession (); session.begintransaction (); // Cache-first-first dan interaksi cache sekunder dilarang sesi.setCachemode (cachemode.ignore); untuk (int i = 0; i <100; i ++) {siswa siswa = siswa baru (); Student.setname ("Zhang San" + i); session.save (siswa); // perbarui setiap 20 item jika (i % 20 == 0) {session.flush (); // Clear Cached Contents Sesi.Clear (); }} session.getTransaction (). commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). rollback (); } akhirnya {hibernateutils.closesession (sesi); }}Catatan: session.flush () berarti membersihkan cache tingkat pertama, tetapi kami telah memulai cache tingkat kedua lagi, dan setelah menyimpan (), itu juga menyimpannya ke cache tingkat kedua, tetapi masih ada luapan yang disebabkan oleh cache yang berlebihan. Jadi dalam hal ini kita harus menonaktifkan cache sekunder: session.setCachemode (cachemode.ignore);
Kueri Cache: Baik cache tingkat pertama dan cache cache tingkat kedua kedua objek entitas cache, tetapi kadang-kadang kami berharap untuk mendapatkan atribut tertentu dan tidak sering mengakses database, tetapi mendapatkannya dari cache. Saat ini, kita dapat menggunakan cache kueri. Selain itu, set hasil cache kueri untuk objek entitas akan cache id. Siklus hidup cache kueri diubah. Ketika tabel terkait dimodifikasi, siklus deklarasi cache kueri berakhir, yang tidak ada hubungannya dengan siklus hidup sesi.
1. Ubah file hibernate.cfg.xml untuk mengaktifkan cache kueri. Jika false default, itu tidak diaktifkan. Itu harus ditetapkan sebagai berikut:
<nama properti = "hibernate.cache.use_query_cache"> true </propert>
2. Harus diaktifkan dalam program, seperti:
query.setCacheable (true)
Metode Uji:
public void testCache2 () {session session = null; coba {session = hibernateutils.getSession (); session.begintransaction (); daftar nama = session.createequery ("pilih s.name dari siswa S") .setCeable (true) .list (); for (int i = 0; i <nama. (String) names.get (i); System.out.println (name);} session.getTransaction (). Commit ();} catch (Exception e) {e.printstacktrace (); session.gettransaction (). Rollback ();} akhirnya {Hibernateutils.closession (session);} system.out.println ("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- .list (); for (int i = 0; i <name.size (); i ++) {string name = (string) name.get (i); System.out.println (name);} session.gettransaction (). commit ();} catch (pengecualian e) {e.printStackTrace (); session.gettransaction (). {Hibernateutils.closesession (sesi);}}Catatan: Dalam kode di atas, kami mematikan cache sekunder, nyalakan cache kueri, dan kemudian permintaan properti normal. Jalankan kode uji dan kami dapat menemukan bahwa di sesi pertama, kueri pertama mengeluarkan pernyataan, kemudian menutup sesi, dan kemudian kueri di sesi kedua. Kami akan menemukan bahwa kueri di sesi kedua tidak mengeluarkan pernyataan, yang berarti bahwa cache kueri tidak ada hubungannya dengan siklus hidup sesi.
Konfigurasi cache hibernate.cfg.xml:
<!-Atur antarmuka implementasi untuk menentukan cache sekunder-> <name properti = "hibernate.cache.region.factory_class"> org.hibernate.cache.ehcacheregionfactory </propert> <!-Setel file konfigurasi yang digunakan untuk cache sekunder-<properti </propert> Name = "net.sf.ehcache.configurationResourcename">/ehcache.xml </pruptent> <!-Setel cache menggunakan kueri-> <nama properti = "hibernate.cache.use_query_cache"> true </propert> <!-Muat file hubungan objek pemetaan-> COM/COMM/COM. " Resource = "com/lixue/bean/student.hbm.xml"/> <!-File pemetaan sumber daya (yaitu, file pemetaan entitas) harus diperkenalkan sebelum menyiapkan kelas entitas menggunakan cache level 2-> <class cache usage = "read-only"/
Di atas adalah semua konten artikel ini tentang analisis kode contoh mekanisme cache hibernate, saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!