Den bedste måde at bruge Hibernate TupleTransformer på
Introduktion
I denne artikel vil jeg forklare, hvordan Hibernate TupleTransformer fungerer, og hvordan man bruger den til at erstatte den forældede ResultTransformer.
Den forældede ResultTransformer
Før du bruger Hibernate 6, er ResultTransformer
var standardindstillingen til at transformere et forespørgselsresultatsæt.
Men siden 5.2 er setResultTransformer
metoden for Hibernate Query
grænsefladen blev forældet, selvom der ikke var noget alternativ på det tidspunkt. Grunden til, at denne metode og dens tilknyttede ResultTransformer
grænsefladen blev forældet var, at ResultTransformer
grænsefladen var ikke en funktionel grænseflade.
En funktionel grænseflade giver en enkelt abstrakt metode og kan bruges til at definere et lambda-udtryk. Af denne grund er den gamle ResultTransformer
grænsefladen blev opdelt i to grænseflader TupleTransformer
og ResultListTransformer
, som illustreret i følgende diagram:
Hibernate TupleTransformer
TupleTransformer
definerer transformTuple
metode som følger:
@Incubating @FunctionalInterface public interface TupleTransformer<T> { /** * Tuples are the elements making up each "row" of the query result. * The contract here is to transform these elements into the final * row shape. * * @param tuple The result elements * @param aliases The result aliases ("parallel" array to tuple) * * @return The transformed row. */ T transformTuple(Object[] tuple, String[] aliases); }
transformTuple
metode giver dig mulighed for at transformere standard Object[]
matrixprojektion som følge af JDBC ResultSet
efter at have forbrugt en given post.
Sådan bruger du Hibernate TupleTransformer
Lad os f.eks. sige, at vi har følgende Post
enhed:
@Entity(name = "Post") @Table(name = "post") public class Post { @Id private Long id; private String title; @Column(name = "created_on") private LocalDateTime createdOn; @Column(name = "created_by") private String createdBy; @Column(name = "updated_on") private LocalDateTime updatedOn; @Column(name = "updated_by") private String updatedBy; @Version private Integer version; }
Og vi ønsker at udføre følgende JPQL-forespørgsel, som henter en brugerdefineret projektion:
select p.id, p.title, p.createdOn, p.createdBy, p.updatedOn, p.updatedBy from Post p order by p.id
Som standard, når JPQL-forespørgslen ovenfor udføres, vil projektposterne blive pakket ind i en Object[]
array:
List<Object[]> postRecords = entityManager.createQuery(""" select p.id, p.title, p.createdOn, p.createdBy, p.updatedOn, p.updatedBy from Post p order by p.id """) .getResultList();
Men arbejder med Object[]
array-projektioner er ikke udviklervenlige, så vi ønsker at kortlægge forespørgselsresultatet på følgende Java Record-hierarki:
Til dette formål vil vi bruge en TupleTransformer
der giver os mulighed for at kortlægge standarden Object[]
array-projektion til PostRecord
objekt, som dette:
List<PostRecord> postRecords = entityManager.createQuery(""" select p.id, p.title, p.createdOn, p.createdBy, p.updatedOn, p.updatedBy from Post p order by p.id """) .unwrap(org.hibernate.query.Query.class) .setTupleTransformer( (tuple, aliases) -> { int i =0; return new PostRecord( longValue(tuple[i++]), stringValue(tuple[i++]), new AuditRecord( localDateTimeValue(tuple[i++]), stringValue(tuple[i++]), localDateTimeValue(tuple[i++]), stringValue(tuple[i++]) ) ); } ) .getResultList();
Fedt, ikke?
Konklusion
Hibernate 6 giver en masse nye funktioner, såsom [SQM (Semantic Query Model)(https://vladmihalcea.com/hibernate-sqm-semantic-query-model/) eller support til vinduesfunktioner.
Den nye Hibernate TupleTransformer
skal bruges til at erstatte den gamle ResultTransformer
brug, som den forældede ResultTransformer
vil helt sikkert blive fjernet i en fremtidig version af Hibernate.