Jenis Kueri JPA

1. Ikhtisar

Dalam tutorial ini, kita akan membahas berbagai jenis kueri JPA. Selain itu, kami akan fokus untuk membandingkan perbedaan di antara mereka dan memperluas pro dan kontra masing-masing.

2. Penyiapan

Pertama, mari kita tentukan kelas UserEntity yang akan kita gunakan untuk semua contoh di artikel ini:

@Table(name = "users") @Entity public class UserEntity { @Id private Long id; private String name; //Standard constructor, getters and setters. }

Ada tiga tipe dasar Kueri JPA:

  • Query , ditulis dalam sintaks Java Persistence Query Language (JPQL)
  • NativeQuery , ditulis dalam sintaks SQL biasa
  • Query API Kriteria , dibangun secara terprogram melalui metode yang berbeda

Mari kita jelajahi.

3. Permintaan

Sebuah Query mirip dalam sintaks dengan SQL, dan umumnya digunakan untuk melakukan operasi CRUD:

public UserEntity getUserByIdWithPlainQuery(Long id) { Query jpqlQuery = getEntityManager().createQuery("SELECT u FROM UserEntity u WHERE u.id=:id"); jpqlQuery.setParameter("id", id); return (UserEntity) jpqlQuery.getSingleResult(); }

Query ini mengambil record yang cocok dari tabel users dan juga memetakannya ke objek UserEntity .

Ada dua sub-jenis Kueri tambahan :

  • TypedQuery
  • NamedQuery

Mari kita lihat mereka beraksi.

3.1. TypedQuery

Kita perlu memperhatikan pernyataan return dalam contoh sebelumnya. JPA tidak dapat menyimpulkan apa jenis hasil Query nantinya, dan sebagai hasilnya, kita harus melakukan cast.

Tapi, JPA menyediakan sub-tipe Query khusus yang dikenal sebagai TypedQuery. Ini selalu disukai jika kita mengetahui jenis hasil Query kita sebelumnya. Selain itu, ini membuat kode kami jauh lebih andal dan lebih mudah untuk diuji.

Mari kita lihat alternatif TypedQuery , dibandingkan dengan contoh pertama kita:

public UserEntity getUserByIdWithTypedQuery(Long id) { TypedQuery typedQuery = getEntityManager().createQuery("SELECT u FROM UserEntity u WHERE u.id=:id", UserEntity.class); typedQuery.setParameter("id", id); return typedQuery.getSingleResult(); }

Dengan cara ini, kami mendapatkan pengetikan yang lebih kuat secara gratis, menghindari kemungkinan pengecualian casting di jalan.

3.2. NamedQuery

Meskipun kita dapat secara dinamis mendefinisikan Query pada metode tertentu, mereka pada akhirnya dapat tumbuh menjadi basis kode yang sulit dipertahankan. Bagaimana jika kita dapat menyimpan kueri penggunaan umum di satu tempat yang terpusat dan mudah dibaca?

JPA juga membuat kita membahas hal ini dengan sub-jenis Query lain yang dikenal sebagai NamedQuery.

Kami mendefinisikan NamedQuery pada kelas Entitas itu sendiri, menyediakan cara terpusat, cepat dan mudah untuk membaca dan menemukan kueri terkait Entitas .

Semua NamedQueries harus memiliki nama yang unik.

Mari kita lihat bagaimana kita dapat menambahkan NamedQuery ke kelas UserEntity kita :

@Table(name = "users") @Entity @NamedQuery(name = "UserEntity.findByUserId", query = "SELECT u FROM UserEntity u WHERE u.id=:userId") public class UserEntity { @Id private Long id; private String name; //Standard constructor, getters and setters. }

The @NamedQuery penjelasan harus dikelompokkan di dalam @NamedQueries penjelasan jika kita menggunakan Java sebelum versi 8. Dari Jawa 8 maju, kita hanya bisa mengulangi @NamedQuery penjelasan di kami Entity kelas.

Cara menggunakan NamedQuery sangat sederhana:

public UserEntity getUserByIdWithNamedQuery(Long id) { Query namedQuery = getEntityManager().createNamedQuery("UserEntity.findByUserId"); namedQuery.setParameter("userId", id); return (UserEntity) namedQuery.getSingleResult(); }

4. NativeQuery

Sebuah NativeQuery hanyalah sebuah query SQL. Ini memungkinkan kami untuk menggunakan kekuatan penuh database kami, karena kami dapat menggunakan fitur berpemilik yang tidak tersedia dalam sintaks yang dibatasi JPQL.

This comes at a cost. We lose database portability of our application with NativeQuery because our JPA provider can't abstract specific details from the database implementation or vendor anymore.

Let's see how to use a NativeQuery that yields the same results as our previous examples:

public UserEntity getUserByIdWithNativeQuery(Long id) { Query nativeQuery = getEntityManager().createNativeQuery("SELECT * FROM users WHERE id=:userId", UserEntity.class); nativeQuery.setParameter("userId", id); return (UserEntity) nativeQuery.getSingleResult(); }

We must always consider if a NativeQuery is the only option. Most of the time, a good JPQL Query can fulfill our needs and most importantly, maintain a level of abstraction from the actual database implementation.

Menggunakan NativeQuery tidak selalu berarti mengunci diri kita sendiri ke satu vendor database tertentu. Lagi pula, jika kueri kami tidak menggunakan perintah SQL berpemilik dan hanya menggunakan sintaks SQL standar, beralih penyedia seharusnya tidak menjadi masalah.

5. Query API Kriteria

Kueri API Kriteria adalah kueri yang dibuat secara terprogram dan aman jenis - agak mirip dengan kueri JPQL dalam sintaks:

public UserEntity getUserByIdWithCriteriaQuery(Long id) { CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder(); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(UserEntity.class); Root userRoot = criteriaQuery.from(UserEntity.class); UserEntity queryResult = getEntityManager().createQuery(criteriaQuery.select(userRoot) .where(criteriaBuilder.equal(userRoot.get("id"), id))) .getSingleResult(); return queryResult; }

Mungkin menakutkan untuk menggunakan kueri API Kriteria secara langsung, tetapi kueri tersebut bisa menjadi pilihan tepat saat kita perlu menambahkan elemen kueri dinamis atau saat digabungkan dengan Metamodel JPA .

6. Kesimpulan

Dalam artikel singkat ini, kami mempelajari apa itu Kueri JPA, beserta penggunaannya.

Kueri JPA adalah cara terbaik untuk mengabstraksi logika bisnis kita dari lapisan akses data karena kita dapat mengandalkan sintaks JPQL dan membiarkan penyedia pilihan JPA menangani terjemahan Kueri .

Semua kode yang disajikan dalam artikel ini tersedia di GitHub.