Mga Istratehiya ng Concurrency
Pagkatapos mong paganahin ang second-level na caching sa Hibernate, kailangan mong ipaliwanag sa Hibernate kung aling mga Entity object ang gusto naming i-cache at kung paano.
Upang gawin ito, ang Hibernate ay may espesyal na anotasyon para sa mga klase ng Entity - @Cache . Halimbawa:
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
Kailangang isulat ang anotasyong ito para sa bawat entity ng Entity kung saan gusto naming gamitin ang cache ng pangalawang antas. Halimbawa:
@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
@Id
private Integer id;
private Set<Task> tasks;
}
Ang hibernate ay may 4 na posibleng diskarte sa pag-access para sa isang naka-cache na entity kung ito ay na-access mula sa iba't ibang mga thread:
- Basahin lamang
- basa sulat
- nonstrict-read-write
- transactional
Read -only. Isang diskarte sa concurrency na naaangkop sa data na hindi nagbabago. Iimbak lamang ng hibernate ang mga bagay na ito sa memorya nito. Gamitin ito para sa reference data lamang.
Ang mga database ay nag-iimbak ng maraming impormasyon na hindi nagbabago. Halimbawa, ang isang talahanayan ay nagpapanatili ng isang listahan ng mga kaganapan na idinagdag lamang ngunit hindi kailanman binago o inalis. Kung kailangan mong magtrabaho kasama ang talahanayang ito sa pamamagitan ng Hibernate, ang read-only na diskarte sa pag-cache ay babagay sa iyo.
Magbasa-magsulat (read-write). Gamitin ang diskarteng ito para sa data na pangunahing nababasa. Gayunpaman, susubaybayan ng Hibernate ang mga pagtatangka na baguhin ang data na ito, bagama't inaasahan nitong madalang ang mga ito.
Kailangan mong i-cache ang pangunahing mga bagay na bihirang magbago at madalas na binabasa / hiniling. Kung mayroon kang ganoong mga bagay, kailangan mong gamitin ang diskarteng read-write para sa kanila.
Nonstrict-read-write . Hindi ginagarantiyahan ng diskarteng ito ang pagkakapare-pareho sa pagitan ng cache at ng database. Gamitin ang diskarteng ito kung ang data ay halos hindi nagbabago at ang isang maliit na pagkakataon ng lipas na data ay hindi isang kritikal na isyu.
Hindi tulad ng diskarte sa read-write, ipinapalagay ng diskarteng ito na hindi naka-lock para sa pagbabasa ang nababagong data. Maaari itong magresulta sa pagbabago ng bagay sa isang lugar, habang sa isa pa, may nagbabasa ng lumang bersyon nito.
Halimbawa, binago ng isang user ang kanyang komento, ngunit nakikita pa rin ng ibang mga user ang kanyang lumang bersyon sa loob ng ilang panahon. Kung ito ay hindi isang problema para sa iyo, pagkatapos ay gamitin ang nonstrict-read-write na diskarte.
Transaksyonal . Gamitin ang diskarteng ito para sa pangunahing read-only na data kung saan mahalagang pigilan ang lipas na data sa mga kasabay na transaksyon sa pambihirang pagkakataon ng isang update.
Pag-iimbak ng data sa isang cache
Ang isa pang mahalagang detalye tungkol sa pangalawang antas ng cache na dapat mong tandaan ay ang Hibernate ay hindi nag-iimbak ng mga bagay ng iyong mga klase mismo. Nag-iimbak ito ng impormasyon bilang mga hanay ng mga string, numero, atbp.
At ang object identifier ay nagsisilbing pointer sa impormasyong ito. Conceptually, ito ay isang bagay tulad ng isang Map, kung saan ang id ng object ay ang susi, at ang data arrays ay ang halaga. Maaari mong isipin ito tulad nito:
1 -> { "Ivanov", 1, null , {1,2,5} }
2 -> { "Petrov", 2, null , {1,2,5} }
3 -> { "Sidorov", 3, null , {1,2,5} }
Na kung saan ay napaka-makatwirang isinasaalang-alang kung gaano karaming dagdag na memorya ang kinukuha ng bawat bagay.
Bilang karagdagan sa itaas, dapat mong tandaan na ang mga dependency ng iyong klase ng Entity ay hindi rin naka-cache bilang default. Halimbawa, kung isasaalang-alang namin ang klase sa itaas, Empleyado , pagkatapos kapag kinukuha, ang koleksyon ng mga gawain ay kukunin mula sa database , at hindi mula sa pangalawang antas na cache .
Kung gusto mo ring mag-cache ng mga dependency, dapat ganito ang hitsura ng klase:
@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
@Id
private Integer id;
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<Task> tasks;
}
At ang huling detalye - ang pagbabasa mula sa pangalawang antas ng cache ay nangyayari lamang kung ang nais na bagay ay hindi natagpuan sa unang antas ng cache.
CacheMode
Ang hibernate ay nagbibigay-daan para sa napaka-flexible na pamamahala ng caching. Maaari mong itakda ang cache mode para sa bawat indibidwal na session o kahit para sa bawat kahilingan sa database.
Mayroong limang gayong mga mode:
- GET
- HUWAG PANSININ
- NORMAL
- ILAGAY
- REFRESH
Inilalarawan ng talahanayan sa ibaba ang kanilang gawain:
CacheMode | Paglalarawan |
---|---|
GET | Ang data ay binabasa mula sa cache ngunit hindi idinagdag dito. |
HUWAG PANSININ | Ang session ay hindi nakikipag-ugnayan sa cache. |
NORMAL | Ang data ay binabasa mula sa cache at idinagdag dito. |
ILAGAY | Ang data ay hindi kailanman kinukuha mula sa cache, ngunit idinagdag dito. |
REFRESH | Ang data ay hindi kailanman kinukuha mula sa cache, ngunit idinagdag dito. Sa mode na ito, ang setting ng hibernate.cache.use_minimal_puts ay dagdag na ginagamit. |
Isang halimbawa ng pagtatakda ng cache mode para sa isang session:
session.setCacheMode(CacheMode.GET);
Employee director = session.createQuery("from Employee where id = 4").uniqueResult();
At isa ring halimbawa ng pagtatakda ng mode para sa session at kahilingan:
session.setCacheMode(CacheMode.GET);
Query query = session.createQuery("from Employee where id = 4");
query.setCacheMode(CacheMode.IGNORE); // Ignore cache work for this request
Employee director = query.uniqueResult();