NativeQuery

All lectures for BG purposes
Ниво , Урок
На разположение

3.1 Въведение

Друго полезно нещо, за което бих искал да говоря, е NativeQuery . Както вече знаете, с помощта на NativeQuery можете да пишете заявки в естествен SQL. Още по-интересното обаче е, че не е нужно да използвате картографиране на класове, когато получавате резултата от заявката.

Предпочитам да ви покажа един пример:

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

В този пример ние не предаваме клас, който съответства на редовете с резултати от заявката, instead of това просто използваме масив от обекти Object.

Това може да бъде полезно, ако искате да изберете само няколко колони в table. Пример:


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

Това е донякъде подобно на подхода на JDBC, когато получавате ResultSet обект и четете данни от неговите редове.

Hibernate обаче предлага различни начини да направите това по-надеждно. Например, можете да посочите типа колони, които искате да извадите. Пример:


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 Картографиране на обекти

Можете също изрично да посочите класа, който Hibernate трябва да използва, когато анализира резултата от NativeQuery . Това може да стане по различни начини.


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

И разбира се, добрият стар формат, който познавате:


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

Първият подход е естественият подход на Hibernate, а вторият е подходът JPA. Подходът на JPA е по-удобен и кратък, тъй като този стандарт е изобретен, след като Hibernate съществува в продължение на много години. И Hibernate се разви и беше принуден да поддържа стари подходи, за да поддържа съвместимост със старите си версии.

Между другото, благодарение на своя подход, Hibernate ви позволява да свържете не един клас към картографирането на резултатите от заявката, а няколко класа. Пример:


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

Този подход, използващ NativeQuery , може да се използва за ускоряване на селекцията на данни от базата данни. Ако знаете, че не се нуждаете от някои колони, можете да ги оставите в заявката.

Можете също така да заредите всички дъщерни обекти наведнъж, дори ако Hibernate иска да използва Cache or LazyLoading механизма . Освен това вашите дъщерни обекти може да имат много колони в базата данни и можете да изберете само някои от тях.

3.3 Картографиране на DTO

Hibernate също ви позволява да използвате класове, които не са Entity, за картографиране на резултата. Класове, които нямат анотации и не са съпоставени с ниHowви таблици.

Пример:

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

Тъй като в класа PersonSummaryDTO няма анотации, имената на колоните в SQL заявката трябва точно да съвпадат с имената на полетата на класа PersonSummaryDTO.

Това може да бъде много полезно, ако четете данни от външна база данни, към която вашето приложение е свързано само в режим само за четене. Тоест ви беше даден достъп до таблици, които имат 50+ колони, те съхраняват данни в денормализирана форма, за да ускорят селекцията.

Или да кажем, че някой е решил да съхрани класовата йерархия в една table и за пет години тази table е нараснала толкова много, че дяволът ще му счупи крака. Трябва да изберете няколко колони от тази table (Id и потребителско име) и да ги дадете на клиента.

Мисля, че разбирате, но ако искате да се потопите по-дълбоко в тази тема, можете да прочетете повече на линка:

Нативни SQL заявки

Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION