3.1 Inleiding

Een ander nuttig ding waar ik het over wil hebben is NativeQuery . Zoals u al weet, kunt u met NativeQuery query's schrijven in native SQL. Wat echter nog interessanter is, is dat u geen klassentoewijzing hoeft te gebruiken bij het ophalen van het queryresultaat.

Ik laat je liever een voorbeeld zien:

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

In dit voorbeeld geven we geen klasse door die overeenkomt met de resultaatrijen van de query, maar gebruiken we alleen een reeks objectobjecten.

Dit kan handig zijn als u slechts een paar kolommen in een tabel wilt selecteren. Voorbeeld:


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];
}

Dit lijkt enigszins op de JDBC-benadering wanneer u een ResultSet-object krijgt en gegevens uit de rijen ervan leest.

Hibernate biedt echter verschillende manieren om dit betrouwbaarder te maken. U kunt bijvoorbeeld het type kolommen opgeven dat u wilt aftrekken. Voorbeeld:


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 Entiteitsmapping

U kunt ook expliciet de klasse specificeren die Hibernate moet gebruiken bij het ontleden van het resultaat van NativeQuery . Dit kan op verschillende manieren.


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

En natuurlijk het goede oude formaat dat je kent:


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

De eerste benadering is de native Hibernate-benadering en de tweede is de JPA-benadering. De JPA-benadering is handiger en beknopter, aangezien deze standaard is uitgevonden nadat Hibernate vele jaren bestond. En Hibernate evolueerde en werd gedwongen om oude benaderingen te ondersteunen om de compatibiliteit met zijn oude versies te behouden.

Trouwens, dankzij zijn aanpak kunt u met Hibernate niet één klasse verbinden met de toewijzing van queryresultaten, maar meerdere klassen. Voorbeeld:


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() );
}

Deze benadering met behulp van NativeQuery kan worden gebruikt om de selectie van gegevens uit de database te versnellen. Als u weet dat u sommige kolommen niet nodig heeft, kunt u deze weglaten in de aanvraag.

U kunt ook alle onderliggende entiteiten tegelijk laden, zelfs als Hibernate Cache of het LazyLoading -mechanisme wil gebruiken . Bovendien kunnen uw onderliggende entiteiten veel kolommen in de database hebben en kunt u er slechts enkele selecteren.

3.3 DTO-mapping

Met Hibernate kunt u ook niet-entiteitsklassen gebruiken om het resultaat in kaart te brengen. Klassen die geen annotaties hebben en niet aan tabellen zijn toegewezen.

Voorbeeld:

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();

Aangezien er geen annotaties zijn in de klasse PersonSummaryDTO, moeten de namen van de kolommen in de SQL-query exact overeenkomen met de namen van de velden van de klasse PersonSummaryDTO.

Dit kan erg handig zijn als u gegevens leest uit een externe database waarmee uw toepassing alleen in alleen-lezenmodus is verbonden. Dat wil zeggen, u kreeg toegang tot tabellen met meer dan 50 kolommen, ze slaan gegevens op in een gedenormaliseerde vorm om de selectie te versnellen.

Of laten we zeggen dat iemand besloot om de klassenhiërarchie in één tabel op te slaan, en in vijf jaar tijd is deze tabel zo gegroeid dat de duivel zijn been zal breken. U moet een aantal kolommen uit deze tabel selecteren (ID en gebruikersnaam) en deze aan de klant geven.

Ik denk dat je het begrijpt, maar als je dieper op dit onderwerp wilt ingaan, kun je meer lezen via de link:

Native SQL-query's