Concurrency-strategieën
Nadat u caching op het tweede niveau in Hibernate hebt ingeschakeld, moet u aan Hibernate uitleggen welke Entity-objecten we willen cachen en hoe.
Om dit te doen, heeft Hibernate een speciale annotatie voor Entity-klassen - @Cache . Voorbeeld:
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
Deze annotatie moet worden geschreven voor elke Entiteitsentiteit waarvoor we de cache op het tweede niveau willen gebruiken. Voorbeeld:
@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
@Id
private Integer id;
private Set<Task> tasks;
}
Hibernate heeft 4 mogelijke toegangsstrategieën voor een entiteit in de cache als deze wordt benaderd vanuit verschillende threads:
- alleen lezen
- lezen schrijven
- niet-strikt-lezen-schrijven
- transactioneel
Alleen lezen . Een data-geschikte gelijktijdigheidsstrategie die nooit verandert. Hibernate slaat deze objecten gewoon op in zijn geheugen. Gebruik het alleen voor referentiegegevens.
Databases slaan veel informatie op die nooit verandert. Een tabel houdt bijvoorbeeld een lijst bij van gebeurtenissen die alleen worden toegevoegd, maar nooit worden gewijzigd of verwijderd. Als u met deze tabel via Hibernate moet werken, dan is de alleen-lezen caching-strategie geschikt voor u.
Lezen-schrijven (lezen-schrijven). Gebruik deze strategie voor gegevens die voornamelijk leesbaar zijn. Hibernate zal echter pogingen volgen om deze gegevens te wijzigen, hoewel het verwacht dat dit zeer zeldzaam zal zijn.
U moet voornamelijk die objecten cachen die zelden veranderen en vaak worden gelezen/opgevraagd. Als u dergelijke objecten hebt, moet u hiervoor de lees-schrijfstrategie gebruiken.
Niet-strikt-lezen-schrijven . Deze strategie garandeert geen consistentie tussen de cache en de database. Gebruik deze strategie als de gegevens bijna nooit veranderen en een kleine kans op verouderde gegevens geen kritiek probleem is.
In tegenstelling tot de lees-schrijfstrategie, gaat deze strategie ervan uit dat veranderlijke gegevens niet zijn vergrendeld voor lezen. Dit kan ertoe leiden dat het object op de ene plaats wordt gewijzigd, terwijl op een andere plaats iemand de oude versie ervan leest.
Een gebruiker heeft bijvoorbeeld zijn opmerking gewijzigd, maar andere gebruikers zien nog enige tijd zijn oude versie. Als dit geen probleem voor u is, gebruik dan de niet-strikte lees-schrijfstrategie.
Transactioneel . Gebruik deze strategie voor voornamelijk alleen-lezen gegevens waarbij het belangrijk is om verouderde gegevens in gelijktijdige transacties te voorkomen in het zeldzame geval van een update.
Gegevens opslaan in een cache
Een ander belangrijk detail over de cache op het tweede niveau dat u moet onthouden, is dat Hibernate de objecten van uw klassen niet zelf opslaat. Het slaat informatie op als arrays van strings, getallen, enz.
En de object-ID fungeert als een verwijzing naar deze informatie. Conceptueel is dit zoiets als een kaart, waarin de id van het object de sleutel is en de gegevensarrays de waarde. Je kunt het je zo voorstellen:
1 -> { "Ivanov", 1, null , {1,2,5} }
2 -> { "Petrov", 2, null , {1,2,5} }
3 -> { "Sidorov", 3, null , {1,2,5} }
Dat is heel redelijk als je bedenkt hoeveel extra geheugen elk object in beslag neemt.
Naast het bovenstaande moet u onthouden dat de afhankelijkheden van uw Entity-klasse ook niet standaard in de cache worden opgeslagen. Als we bijvoorbeeld kijken naar de klasse hierboven, Employee , dan wordt bij het ophalen de verzameling taken opgehaald uit de database en niet uit de cache op het tweede niveau .
Als je ook afhankelijkheden wilt cachen, dan zou de klasse er als volgt uit moeten zien:
@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;
}
En het laatste detail: het lezen van de cache op het tweede niveau vindt alleen plaats als het gewenste object niet is gevonden in de cache op het eerste niveau.
CacheMode
Hibernate zorgt voor zeer flexibel cachingbeheer. U kunt de cachemodus instellen voor elke afzonderlijke sessie of zelfs voor elke databaseaanvraag.
Er zijn vijf van dergelijke modi:
- KRIJGEN
- NEGEREN
- NORMAAL
- NEERZETTEN
- VERFRISSEN
De onderstaande tabel beschrijft hun werk:
CacheMode | Beschrijving |
---|---|
KRIJGEN | Gegevens worden uit de cache gelezen maar er niet aan toegevoegd. |
NEGEREN | De sessie heeft geen interactie met de cache. |
NORMAAL | Gegevens worden uit de cache gelezen en eraan toegevoegd. |
NEERZETTEN | Gegevens worden nooit uit de cache gehaald, maar eraan toegevoegd. |
VERFRISSEN | Gegevens worden nooit uit de cache gehaald, maar eraan toegevoegd. In deze modus wordt bovendien de instelling hibernate.cache.use_minimal_puts gebruikt. |
Een voorbeeld van het instellen van de cachemodus voor een sessie:
session.setCacheMode(CacheMode.GET);
Employee director = session.createQuery("from Employee where id = 4").uniqueResult();
En ook een voorbeeld van het instellen van de modus voor de sessie en het verzoek:
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();