3.1 Pengenalan

Satu lagi perkara berguna yang saya ingin bincangkan ialah NativeQuery . Seperti yang anda sedia maklum, menggunakan NativeQuery, anda boleh menulis pertanyaan dalam SQL asli. Walau bagaimanapun, apa yang lebih menarik ialah anda tidak perlu menggunakan pemetaan kelas apabila mendapat hasil pertanyaan.

Saya lebih suka menunjukkan kepada anda contoh:

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

Dalam contoh ini, kami tidak lulus kelas yang sepadan dengan baris hasil pertanyaan, sebaliknya kami hanya menggunakan tatasusunan objek Objek.

Ini boleh berguna jika anda mahu memilih hanya beberapa lajur dalam jadual. Contoh:


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

Ini agak serupa dengan pendekatan JDBC apabila anda mendapat objek ResultSet dan membaca data daripada barisnya.

Walau bagaimanapun, Hibernate menawarkan cara yang berbeza untuk menjadikannya lebih dipercayai. Sebagai contoh, anda boleh menentukan jenis lajur yang anda ingin tolak. Contoh:


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 Pemetaan entiti

Anda juga boleh menentukan secara eksplisit kelas yang harus digunakan oleh Hibernate apabila menghuraikan hasil NativeQuery . Ini boleh dilakukan dengan cara yang berbeza.


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

Dan sudah tentu, format lama yang baik yang anda tahu:


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

Pendekatan pertama ialah pendekatan Hibernate asli dan kedua ialah pendekatan JPA. Pendekatan JPA adalah lebih mudah dan ringkas, kerana piawaian ini dicipta selepas Hibernate wujud selama bertahun-tahun. Dan Hibernate berkembang dan terpaksa menyokong pendekatan lama untuk mengekalkan keserasian dengan versi lamanya.

Dengan cara ini, terima kasih kepada pendekatannya, Hibernate membenarkan anda menyambungkan bukan satu kelas ke pemetaan hasil pertanyaan, tetapi beberapa kelas. Contoh:


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

Pendekatan menggunakan NativeQuery ini boleh digunakan untuk mempercepatkan pemilihan data daripada pangkalan data. Jika anda tahu bahawa anda tidak memerlukan beberapa lajur, anda boleh meninggalkannya dalam permintaan.

Anda juga boleh memuatkan semua entiti anak sekali gus, walaupun Hibernate mahu menggunakan Cache atau mekanisme LazyLoading . Di samping itu, entiti anak anda mungkin mempunyai banyak lajur dalam pangkalan data dan anda boleh memilih hanya sebahagian daripadanya.

3.3 Pemetaan DTO

Hibernate juga membenarkan anda menggunakan kelas bukan Entiti untuk memetakan hasil. Kelas yang tidak mempunyai sebarang anotasi dan tidak dipetakan ke mana-mana jadual.

Contoh:

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

Memandangkan tiada anotasi dalam kelas PersonSummaryDTO, nama lajur dalam pertanyaan SQL mesti sepadan dengan nama medan kelas PersonSummaryDTO.

Ini boleh menjadi sangat berguna jika anda membaca data daripada pangkalan data luaran yang aplikasi anda disambungkan hanya dalam mod baca sahaja. Iaitu, anda diberi akses kepada jadual yang mempunyai 50+ lajur, ia menyimpan data dalam bentuk yang tidak normal untuk mempercepatkan pemilihan.

Atau katakan bahawa seseorang memutuskan untuk menyimpan hierarki kelas dalam satu jadual, dan dalam lima tahun jadual ini telah berkembang begitu banyak sehingga syaitan akan mematahkan kakinya. Anda perlu memilih beberapa lajur daripada jadual ini (Id dan nama pengguna) dan memberikannya kepada pelanggan.

Saya rasa anda faham, tetapi jika anda ingin mendalami topik ini, anda boleh membaca lebih lanjut di pautan:

Pertanyaan SQL Asli