3.1 Wprowadzenie

Kolejną użyteczną rzeczą, o której chciałbym porozmawiać, jest NativeQuery . Jak już wiesz, używając NativeQuery możesz pisać zapytania w natywnym SQL. Jednak jeszcze bardziej interesujące jest to, że nie musisz używać mapowania klas podczas uzyskiwania wyniku zapytania.

Raczej pokażę ci przykład:

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

W tym przykładzie nie przekazujemy klasy, która pasuje do wierszy wyników zapytania, zamiast tego używamy po prostu tablicy obiektów Object.

Może to być przydatne, jeśli chcesz zaznaczyć tylko kilka kolumn w tabeli. Przykład:


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

Jest to nieco podobne do podejścia JDBC, kiedy otrzymujesz obiekt ResultSet i odczytujesz dane z jego wierszy.

Jednak Hibernate oferuje różne sposoby zwiększenia niezawodności. Na przykład możesz określić typ kolumn, które chcesz odjąć. Przykład:


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 Mapowanie jednostek

Możesz także jawnie określić klasę, której Hibernate powinien używać podczas analizowania wyniku NativeQuery . Można to zrobić na różne sposoby.


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

I oczywiście stary dobry format, który znasz:


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

Pierwsze podejście to natywne podejście Hibernate, a drugie to podejście JPA. Podejście JPA jest wygodniejsze i bardziej zwięzłe, ponieważ ten standard został wynaleziony po wielu latach istnienia Hibernate. A Hibernate ewoluował i został zmuszony do wspierania starych podejść, aby zachować kompatybilność ze starymi wersjami.

Nawiasem mówiąc, dzięki swojemu podejściu, Hibernate pozwala na podłączenie nie jednej klasy do mapowania wyniku zapytania, ale kilku klas. Przykład:


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

Takie podejście z wykorzystaniem NativeQuery może być wykorzystane do przyspieszenia selekcji danych z bazy danych. Jeśli wiesz, że nie potrzebujesz niektórych kolumn, możesz je pominąć w żądaniu.

Możesz także załadować wszystkie jednostki potomne naraz, nawet jeśli Hibernate chce użyć mechanizmu Cache lub LazyLoading . Ponadto Twoje jednostki podrzędne mogą mieć wiele kolumn w bazie danych i możesz wybrać tylko niektóre z nich.

3.3 Mapowanie DTO

Hibernate pozwala również na użycie klas innych niż Entity do mapowania wyniku. Klasy, które nie mają żadnych adnotacji i nie są mapowane na żadne tabele.

Przykład:

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

Ponieważ w klasie PersonSummaryDTO nie ma adnotacji, nazwy kolumn w zapytaniu SQL muszą dokładnie odpowiadać nazwom pól klasy PersonSummaryDTO.

Może to być bardzo przydatne, jeśli odczytujesz dane z zewnętrznej bazy danych, do której aplikacja jest podłączona tylko w trybie tylko do odczytu. Oznacza to, że otrzymałeś dostęp do tabel, które mają ponad 50 kolumn, przechowują dane w zdenormalizowanej formie, aby przyspieszyć wybór.

Albo powiedzmy, że ktoś postanowił schować hierarchię klas w jednej tabeli, aw ciągu pięciu lat ta tabela urosła tak bardzo, że diabeł złamie sobie nogę. Musisz wybrać kilka kolumn z tej tabeli (Id i username) i przekazać je klientowi.

Myślę, że rozumiesz, ale jeśli chcesz zagłębić się w ten temat, możesz przeczytać więcej pod linkiem:

Natywne zapytania SQL