NativeQuery

Disponibile

3.1 Introduzione

Un'altra cosa utile di cui vorrei parlare è NativeQuery . Come già sai, utilizzando NativeQuery, puoi scrivere query in SQL nativo. Tuttavia, ciò che è ancora più interessante è che non è necessario utilizzare la mappatura delle classi quando si ottiene il risultato della query.

Preferisco mostrarti un esempio:

List<Object[]> persons = session.createNativeQuery("SELECT * FROM Person").list();

In questo esempio, non passiamo una classe che corrisponda alle righe dei risultati della query, invece usiamo solo un array di oggetti Object.

Questo può essere utile se vuoi selezionare solo un paio di colonne in una tabella. Esempio:

List<Object[]> persons = session.createNativeQuery("SELECT id, name FROM Person").list();

for(Object[] person : persons) {
    Number id = (Number) person[0];
    String name = (String) person[1];
}

Questo è in qualche modo simile all'approccio JDBC quando ottieni un oggetto ResultSet e leggi i dati dalle sue righe.

Tuttavia, Hibernate offre diversi modi per renderlo più affidabile. Ad esempio, puoi specificare il tipo di colonne che vuoi sottrarre. Esempio:

Query<Object[]> query = session.createNativeQuery("SELECT id, name FROM Person");
query.addScalar("id", StandardBasicTypes.LONG);
query.addScalar("name", StandardBasicTypes.STRING);
List<Object[]> persons = query.list();

for(Object[] person : persons) {
    Long id = (Long) person[0];
    String name = (String) person[1];
}

3.2 Mappatura delle entità

Puoi anche specificare esplicitamente la classe che Hibernate dovrebbe usare durante l'analisi del risultato di NativeQuery . Questo può essere fatto in diversi modi.

Query<Person> query = session.createNativeQuery("SELECT * FROM Person")
    .addEntity(Person.class);
    .list();

E, naturalmente, il buon vecchio formato che conosci:

Query<Person> query = session.createNativeQuery("SELECT * FROM Person", Person.class).list();

Il primo approccio è l'approccio nativo di Hibernate e il secondo è l'approccio JPA. L'approccio JPA è più conveniente e conciso, poiché questo standard è stato inventato dopo che Hibernate esisteva per molti anni. E Hibernate si è evoluto ed è stato costretto a supportare vecchi approcci per mantenere la compatibilità con le sue vecchie versioni.

A proposito, grazie al suo approccio, Hibernate ti consente di connettere non una classe alla mappatura dei risultati della query, ma diverse classi. Esempio:

List<Phone> results = session.createNativeQuery(
    "SELECT {ph.*}, {pr.*}" +
    "FROM Phone ph" +
    "JOIN Person pr ON ph.person_id = pr.id")
.addEntity("ph", Phone.class)
.addJoin("pr", "ph.person")
.list();

for (Phone. phone : results) {
           	assertNotNull( phone.getPerson().getName() );
}

Questo approccio che utilizza NativeQuery può essere utilizzato per velocizzare la selezione dei dati dal database. Se sai che non hai bisogno di alcune colonne, puoi ometterle nella richiesta.

Puoi anche caricare tutte le entità figlio contemporaneamente, anche se Hibernate desidera utilizzare Cache o il meccanismo LazyLoading . Inoltre, le tue entità figlio potrebbero avere molte colonne nel database ed è possibile selezionarne solo alcune.

3.3 Mappatura DTO

Hibernate consente inoltre di utilizzare classi non Entity per mappare il risultato. Classi che non hanno annotazioni e non sono mappate ad alcuna tabella.

Esempio:

public class PersonSummaryDTO {
    private Number id;
    private String name;

    public Number getId() {
    	return id;
    }

    public void setId(Number id) {
    	this.id = id;
    }

    public String getName() {
    	return name;
    }

    public void setName(String name) {
    	this.name = name;
	}
}

List<PersonSummaryDTO> dtos = session.createNativeQuery(
    "SELECT p.id as \"id\", p.name as \"name\" FROM Person p")
.setResultTransformer(Transformers.aliasToBean(PersonSummaryDTO.class) )
.list();

Poiché non sono presenti annotazioni nella classe PersonSummaryDTO, i nomi delle colonne nella query SQL devono corrispondere esattamente ai nomi dei campi della classe PersonSummaryDTO.

Questo può essere molto utile se stai leggendo dati da un database esterno a cui la tua applicazione è connessa solo in modalità di sola lettura. Cioè, ti è stato dato l'accesso a tabelle con più di 50 colonne, memorizzano i dati in una forma denormalizzata per accelerare la selezione.

Oppure diciamo che qualcuno ha deciso di conservare la gerarchia di classe in un tavolo, e in cinque anni questo tavolo è cresciuto così tanto che il diavolo gli romperà una gamba. Devi selezionare un paio di colonne da questa tabella (Id e nome utente) e consegnarle al cliente.

Penso che tu capisca, ma se vuoi approfondire questo argomento, puoi leggere di più al link:

Query SQL native

Commenti
  • Popolari
  • Nuovi
  • Vecchi
Devi avere effettuato l'accesso per lasciare un commento
Questa pagina non ha ancora commenti