3.1 Panimula

Ang isa pang kapaki-pakinabang na bagay na gusto kong pag-usapan ay ang NativeQuery . Tulad ng alam mo na, gamit ang NativeQuery, maaari kang magsulat ng mga query sa native SQL. Gayunpaman, ang mas kawili-wili ay hindi mo kailangang gumamit ng pagmamapa ng klase kapag nakuha ang resulta ng query.

Mas gusto kong magpakita sa iyo ng isang halimbawa:

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

Sa halimbawang ito, hindi kami pumasa sa isang klase na tumutugma sa mga hilera ng resulta ng query, sa halip ay gumagamit lang kami ng hanay ng mga bagay na Bagay.

Maaari itong maging kapaki-pakinabang kung gusto mong pumili lamang ng ilang column sa isang table. Halimbawa:


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

Ito ay medyo katulad ng JDBC approach kapag nakakuha ka ng ResultSet object at nagbasa ng data mula sa mga row nito.

Gayunpaman, nag-aalok ang Hibernate ng iba't ibang paraan upang gawin itong mas maaasahan. Halimbawa, maaari mong tukuyin ang uri ng mga column na gusto mong ibawas. Halimbawa:


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 Pagmamapa ng entity

Maaari mo ring tahasang tukuyin ang klase na dapat gamitin ng Hibernate kapag nag-parse ng resulta ng NativeQuery . Ito ay maaaring gawin sa iba't ibang paraan.


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

At siyempre, ang magandang lumang format na alam mo:


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

Ang unang diskarte ay ang katutubong Hibernate approach at ang pangalawa ay ang JPA approach. Ang diskarte ng JPA ay mas maginhawa at maigsi, dahil ang pamantayang ito ay naimbento pagkatapos umiral ang Hibernate sa loob ng maraming taon. At ang Hibernate ay umunlad at napilitang suportahan ang mga lumang diskarte upang mapanatili ang pagiging tugma sa mga lumang bersyon nito.

Sa pamamagitan ng paraan, salamat sa diskarte nito, pinapayagan ka ng Hibernate na ikonekta ang hindi isang klase sa pagmamapa ng resulta ng query, ngunit maraming mga klase. Halimbawa:


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

Ang diskarteng ito gamit ang NativeQuery ay maaaring gamitin upang pabilisin ang pagpili ng data mula sa database. Kung alam mong hindi mo kailangan ng ilang column, maaari mong iwanan ang mga ito sa kahilingan.

Maaari mo ring i-load ang lahat ng child entity nang sabay-sabay, kahit na gusto ng Hibernate na gumamit ng Cache o ang LazyLoading na mekanismo . Bilang karagdagan, ang mga entity ng iyong anak ay maaaring may maraming mga column sa database, at maaari mo lamang piliin ang ilan sa mga ito.

3.3 Pagmamapa ng DTO

Hinahayaan ka rin ng hibernate na gumamit ng mga klase na hindi Entity para sa pagmamapa ng resulta. Mga klase na walang anumang anotasyon at hindi namamapa sa anumang mga talahanayan.

Halimbawa:

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

Dahil walang mga anotasyon sa klase ng PersonSummaryDTO, ang mga pangalan ng mga column sa query ng SQL ay dapat na eksaktong tumugma sa mga pangalan ng mga field ng klase ng PersonSummaryDTO.

Maaari itong maging lubhang kapaki-pakinabang kung nagbabasa ka ng data mula sa isang panlabas na database kung saan nakakonekta lamang ang iyong application sa read-only na mode. Ibig sabihin, binigyan ka ng access sa mga talahanayan na mayroong 50+ column, nag-iimbak sila ng data sa isang denormalized na form upang mapabilis ang pagpili.

O sabihin natin na may nagpasya na iimbak ang hierarchy ng klase sa isang table, at sa loob ng limang taon ang talahanayang ito ay lumaki nang husto na ang diyablo ay mabali ang kanyang binti. Kailangan mong pumili ng ilang column mula sa talahanayang ito (Id at username) at ibigay ang mga ito sa kliyente.

Sa palagay ko naiintindihan mo, ngunit kung gusto mong sumisid nang mas malalim sa paksang ito, maaari kang magbasa nang higit pa sa link:

Native SQL Query