Java >> Java tutorial >  >> Tag >> native

Dvale-tip:Sådan kontrollerer du cache-invalidering for indbyggede forespørgsler

Hibernate Tips er en række indlæg, hvor jeg beskriver en hurtig og nem løsning på almindelige Hibernate-spørgsmål. Hvis du har et spørgsmål til et fremtidigt Hibernate Tip, bedes du skrive en kommentar nedenfor.

Spørgsmål:

"Jeg fik at vide, at native forespørgsler fjerner alle enheder fra min cache på 2. niveau. Men du anbefaler dem stadig. Påvirker de ikke ydeevnen negativt?”

Løsning:

Ja, nogle indbyggede forespørgsler ugyldiggør cachen på 2. niveau. Men nej, hvis du gør det korrekt, har det ingen negative virkninger på ydeevnen, og det ændrer ikke på min anbefaling om at bruge dem.

For at besvare dette spørgsmål mere detaljeret skal vi først diskutere, hvilke typer indbyggede forespørgsler, der ugyldiggør cachen på 2. niveau, før vi taler om at finjustere denne proces.

Hvilke indbyggede forespørgsler gør cachen ugyldig?

Native SQL SELECT-sætninger påvirker ikke cachen på 2. niveau, og du behøver ikke bekymre dig om eventuelle negative præstationspåvirkninger. Men Hibernate ugyldiggør cachen på 2. niveau, hvis du udfører en SQL UPDATE- eller DELETE-sætning som en indbygget forespørgsel. Dette er nødvendigt, fordi SQL-sætningen ændrede data i databasen, og dermed kan den have ugyldige entiteter i cachen. Som standard ved Hibernate ikke, hvilke poster der blev påvirket. På grund af dette kan Hibernate kun ugyldiggøre hele cachen på 2. niveau.

Lad os tage et kig på et eksempel.

Før jeg udfører følgende test, vil Author enhed med id 1 er allerede i 2. niveaus cache. Så kører jeg en SQL UPDATE-sætning som en indbygget forespørgsel i én transaktion. I den følgende transaktion kontrollerer jeg, om Forfatteren enhed er stadig i cachen.

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

log.info("Before native update");
log.info("Author 1 in Cache? " + em.getEntityManagerFactory().getCache().contains(Author.class, 1L));

Query q = em.createNativeQuery("UPDATE Book SET title = title || ' - changed'");
q.executeUpdate();

em.getTransaction().commit();
em.close();



em = emf.createEntityManager();
em.getTransaction().begin();

log.info("After native update");
log.info("Author 1 in Cache? " + em.getEntityManagerFactory().getCache().contains(Author.class, 1L));

a = em.find(Author.class, 1L);
log.info(a);

em.getTransaction().commit();
em.close();

Hvis du ikke angiver yderligere oplysninger, ugyldiggør Hibernate cachen på 2. niveau og fjerner alle enheder fra den. Det kan du se i logmeddelelserne skrevet af den 2. transaktion. Forfatteren enhed med id 1 er ikke længere i cachen, og Hibernate skal bruge en forespørgsel for at hente den fra databasen.

06:32:02,752 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - Before native update
06:32:02,752 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - Author 1 in Cache? true
06:32:02,779 DEBUG [org.hibernate.SQL] - UPDATE Book SET title = title || ' - changed'
06:32:02,782 INFO  [org.hibernate.engine.internal.StatisticalLoggingSessionEventListener] - Session Metrics {
    14800 nanoseconds spent acquiring 1 JDBC connections;
    22300 nanoseconds spent releasing 1 JDBC connections;
    201400 nanoseconds spent preparing 1 JDBC statements;
    1356000 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    17500 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}
06:32:02,782 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - After native update
06:32:02,782 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - Author 1 in Cache? false
06:32:02,783 DEBUG [org.hibernate.SQL] - select author0_.id as id1_0_0_, author0_.firstName as firstNam2_0_0_, author0_.lastName as lastName3_0_0_, author0_.version as version4_0_0_ from Author author0_ where author0_.id=?
06:32:02,784 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - Author firstName: Joshua, lastName: Bloch
06:32:02,785 INFO  [org.hibernate.engine.internal.StatisticalLoggingSessionEventListener] - Session Metrics {
    11900 nanoseconds spent acquiring 1 JDBC connections;
    15300 nanoseconds spent releasing 1 JDBC connections;
    18500 nanoseconds spent preparing 1 JDBC statements;
    936400 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    256700 nanoseconds spent performing 1 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    114600 nanoseconds spent performing 1 L2C misses;
    107100 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 0 collections);
    0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}

Ugyldiggør kun berørte områder

Men det behøver ikke at være tilfældet. Du kan fortælle Hibernate, hvilke enhedsklasser der er påvirket af forespørgslen. Du skal bare pakke ud Forespørgslen objekt for at få en Hibernate-specifik SqlQuery , og kald addSynchronizedEntityClass metode med en klassereference.

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

log.info("Before native update");
log.info("Author 1 in Cache? " + em.getEntityManagerFactory().getCache().contains(Author.class, 1L));

Query q = em.createNativeQuery("UPDATE Book SET title = title || ' - changed'");
q.unwrap(NativeQuery.class).addSynchronizedEntityClass(Book.class);
q.executeUpdate();

em.getTransaction().commit();
em.close();



em = emf.createEntityManager();
em.getTransaction().begin();

log.info("After native update");
log.info("Author 1 in Cache? " + em.getEntityManagerFactory().getCache().contains(Author.class, 1L));

a = em.find(Author.class, 1L);
log.info(a);

em.getTransaction().commit();
em.close();

Min SQL UPDATE-sætning ændrer poster i bogen tabel, som bliver kortlagt af bogen enhed. Efter at have givet disse oplysninger til Hibernate, ugyldiggør den online området for bogen entitet og Forfatteren enheder forbliver i cachen på 2. niveau.

06:30:51,985 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - Before native update
06:30:51,985 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - Author 1 in Cache? true
06:30:52,011 DEBUG [org.hibernate.SQL] - UPDATE Book SET title = title || ' - changed'
06:30:52,014 INFO  [org.hibernate.engine.internal.StatisticalLoggingSessionEventListener] - Session Metrics {
    18400 nanoseconds spent acquiring 1 JDBC connections;
    19900 nanoseconds spent releasing 1 JDBC connections;
    86000 nanoseconds spent preparing 1 JDBC statements;
    1825400 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    19400 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}
06:30:52,015 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - After native update
06:30:52,015 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - Author 1 in Cache? true
06:30:52,015 INFO  [org.thoughts.on.java.model.Test2ndLevelCache] - Author firstName: Joshua, lastName: Bloch
06:30:52,016 INFO  [org.hibernate.engine.internal.StatisticalLoggingSessionEventListener] - Session Metrics {
    10000 nanoseconds spent acquiring 1 JDBC connections;
    25700 nanoseconds spent releasing 1 JDBC connections;
    0 nanoseconds spent preparing 0 JDBC statements;
    0 nanoseconds spent executing 0 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    86900 nanoseconds spent performing 1 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    104700 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 0 collections);
    0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}

Få flere oplysninger:

Hvis du vil lære mere om indbyggede forespørgsler eller Hibernates caches, vil du finde følgende artikler interessante:

  • Native Queries – Sådan kalder du native SQL-forespørgsler med JPA
  • Sådan bruger du indbyggede forespørgsler til at udføre masseopdateringer
  • Tip til dvale:Brug QueryCache for at undgå yderligere forespørgsler

Dvaletipsbog







Få flere opskrifter som denne i min nye bog Hibernate Tips:Mere end 70 løsninger på almindelige dvaleproblemer.

Den giver dig mere end 70 klar-til-brug opskrifter til emner som grundlæggende og avancerede kortlægninger, logning, Java 8-understøttelse, caching og statisk og dynamisk definerede forespørgsler.

Få det nu!



Java tag