Java >> Java tutorial >  >> Tag >> hibernate

MutationQuery og SelectionQuery i Hibernate 6

En af de mindre ændringer i Hibernate 6, der nemt kan blive overset, som Steve Ebersole præsenterede i en nylig ekspertsession i Persistence Hub, er introduktionen af ​​MutationQuery og SelectionQuery grænseflader. Det tillader adskillelse mellem forespørgsler, der ændrer data, og dem, der vælger dem fra databasen.

Ældre Hibernate-versioner og JPA-specifikationen bruger Forespørgsel interface til at håndtere begge typer forespørgsler. Det udvider SelectionQuery og MutationQuery grænseflader. Og du kan selvfølgelig stadig bruge den grænseflade med Hibernate 6. Men de 2 nye grænseflader er meget renere, fordi hver enkelt kun definerer de metoder, du kan bruge med den tilsvarende type forespørgsel. Og som jeg vil vise dig i denne artikel, muliggør den også en strengere validering af den leverede erklæring.

Udpakning af en dvale-session

Inden vi ser nærmere på de 2 nye grænseflader, vil jeg hurtigt vise dig, hvordan du får en dvaletilstand session hvis du bruger Hibernate som din JPA-implementering. I så fald injicerer du ofte en EntityManager instans og ikke Hibernates proprietære Session . Du kan få den underliggende session ved at kalde udpakningen metode.

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

Session s = em.unwrap(Session.class);

SelectionQuery – Forespørgsel efter data fra databasen

Få Hibernates SelectionQuery grænsefladen er ret enkel. Når du har fået en session kan du kalde createSelectionQuery metode med en JPQL-forespørgsel String eller en CriteriaQuery objekt.

SelectionQuery<Book> q = s.createSelectionQuery("SELECT b FROM Book b WHERE b.title = :title", Book.class);
q.setParameter("title", "Hibernate Tips - More than 70 solutions to common Hibernate problems");
List<Book> books = q.getResultList();

Du kan også kalde createNamedSelectionQuery metode med navnet på en @NamedQuery .

SelectionQuery<Book> q = s.createNamedSelectionQuery("Book.selectByTitle", Book.class);
q.setParameter("title", "Hibernate Tips - More than 70 solutions to common Hibernate problems");
List<Book> books = q.getResultList();

Forbedret erklæringsvalidering

En af fordelene ved SelectionQuery interface er den forbedrede validering. Når Hibernate instansierer SelectionQuery , validerer den straks forespørgselssætningen.

Session s = em.unwrap(Session.class);
SelectionQuery<Book> q = s.createSelectionQuery("UPDATE Book SET title = upper(title)", Book.class);
List<Book> books = q.getResultList();

Hvis du har angivet en ændring i stedet for en select-sætning, kaster Hibernate en IllegalSelectQueryException .

10:27:35,288 INFO  [com.thorben.janssen.model.TestQueryInterfaces] - Hibernate threw the expected IllegalSelectQueryException.
10:27:35,289 INFO  [com.thorben.janssen.model.TestQueryInterfaces] - org.hibernate.query.IllegalSelectQueryException: Expecting a selection query, but found `UPDATE Book SET title = upper(title)` [UPDATE Book SET title = upper(title)]

Cleaner API

En anden fordel ved SelectionQuery interface er den meget renere grænseflade. Det giver kun metoderne til at konfigurere og udføre en forespørgsel, der udvælger data. Men ingen metoder, der er specifikke for opdateringshandlinger, såsom executeUpdate metode. Du kan finde alle metodedefinitioner i Javadoc. Et par eksempler er:

  • getResultList og getResultStream metoder til at få et forespørgselsresultat, der indeholder flere poster,
  • getSingleResult metode til at få et forespørgselsresultat, der har præcis 1 post,
  • forskellige versioner af setParameter metode til at indstille værdien af ​​en bind-parameter, der bruges i din forespørgsel,
  • det setFirstResult og setMaxResult metoder til at definere paginering,
  • setHint-metoden til at give et forespørgselstip og
  • forskellige metoder til at konfigurere cachehåndteringen.

MutationQuery – Implementering af modificerende forespørgsler

Der er meget færre ting, du kan definere til ændring af forespørgsler, og det er derfor MutationQuery interface drager mest fordel af adskillelsen. MutationQuery grænsefladen er meget renere og nemmere at bruge end Forespørgslen grænseflade ved at udelukke alle udvælgelsesspecifikke metoder. Den definerer kun:

  • den executeUpdate metode til at udføre den ændrende forespørgsel,
  • flere versioner af setParameter metode til at give bindeparameterværdier,
  • 2 metoder til at definere JPA og den Hibernate-specifikke FlushMode og
  • en metode til at indstille en forespørgselstimeout, en forespørgselskommentar og et forespørgselstip.

Definition af en mutationsforespørgsel

Du kan instansiere en MutationQuery på samme måde som SelectionQuery . Hvis du vil bruge en JPQL- eller Criteria-sætning, skal du kalde createMutationQuery metode på Hibernates session grænseflade og angiv en streng med din JPQL-sætning eller en CriteriaUpdate eller Kriterier Slet objekt.

Session s = em.unwrap(Session.class);
MutationQuery q = s.createMutationQuery("UPDATE Book SET title = upper(title)");
q.executeUpdate();

Hvis du definerer en @NamedQuery for din erklæring kan du instansiere den ved at kalde createNamedMutationQuery metode med navnet på din @NamedQuery .

Session s = em.unwrap(Session.class);
MutationQuery q = s.createNamedMutationQuery("Book.updateTitle");
q.executeUpdate();

Ved at kalde createNativeMutationQuery , kan du også instansiere en MutationQuery grænseflade ved hjælp af en indbygget SQL-sætning.

Session s = em.unwrap(Session.class);
MutationQuery q = s.createNativeMutationQuery("UPDATE Book SET title = upper(title)");
q.executeUpdate();

I alle 3 tilfælde returnerer Hibernate en forekomst af den samme MutationQuery interface, som du derefter kan bruge til at konfigurere og udføre din modificerende sætning.

Forbedret validering

Ligesom SelectionQuery interface, validerer Hibernate den angivne erklæring, når du instansierer en MutationQuery . Hvis din angivne erklæring vælger data i stedet for at ændre dem, kaster Hibernate en IllegalMutationQueryException .

Session s = em.unwrap(Session.class);
try {
	MutationQuery q = s.createMutationQuery("SELECT b FROM Book b");
	fail("Expected an IllegalMutationQueryException");
} catch (IllegalMutationQueryException e) {
	log.info("Hibernate threw the expected IllegalMutationQueryException.");
	log.info(e);
}

Som du kan se i log-outputtet, beskriver undtagelsesmeddelelsen tydeligt problemet.

10:42:47,778 INFO  [com.thorben.janssen.model.TestQueryInterfaces] - Hibernate threw the expected IllegalMutationQueryException.
10:42:47,779 INFO  [com.thorben.janssen.model.TestQueryInterfaces] - org.hibernate.query.IllegalMutationQueryException: Expecting a mutation query, but found `SELECT b FROM Book b`

Konklusion

Hibernate 6 bringer en masse ændringer. SelectionQuery og MutationQuery grænseflader er nogle af de mindre. De giver en meget renere API end den ofte brugte Forespørgsel grænseflade, fordi de fokuserer på en bestemt type operation:

  • SelectionQuery interface definerer de metoder, der kræves til at oprette, konfigurere og udføre en forespørgsel, der udvælger data fra databasen.
  • MutationQuery interface gør det samme for UPDATE- og DELETE-sætninger.

Design af en grænseflade til en specifik type operation gjorde det muligt at fjerne alle de unødvendige metoder og designet af meget renere grænseflader.


Java tag