Jenis Pertanyaan JPA

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan membincangkan pelbagai jenis pertanyaan JPA. Lebih-lebih lagi, kami akan memberi tumpuan untuk membandingkan perbezaan di antara mereka dan memperluas kelebihan dan kekurangan masing-masing.

2. Persediaan

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

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

Terdapat tiga jenis pertanyaan JPA asas:

  • Query , ditulis dalam sintaks Java Persistence Query Language (JPQL)
  • NativeQuery , ditulis dalam sintaks SQL biasa
  • Pertanyaan API Kriteria , dibina secara terprogram melalui kaedah yang berbeza

Mari kita meneroka mereka.

3. Pertanyaan

A Pertanyaan adalah sama dalam sintaks SQL, dan ia biasanya digunakan untuk melaksanakan 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(); }

Ini Pertanyaan mendapatkan semula rekod yang hampir sama dari pengguna meja dan juga maps kepada UserEntity objek.

Terdapat dua sub-jenis Pertanyaan tambahan :

  • Pertanyaan Diketik
  • DinamakanQuery

Mari lihat mereka beraksi.

3.1. Pertanyaan Diketik

Kita perlu memperhatikan penyataan pengembalian dalam contoh sebelumnya. JPA tidak dapat menyimpulkan apa jenis hasil Pertanyaan , dan, sebagai hasilnya, kita harus membuang.

Tetapi, JPA menyediakan sub-jenis Query khas yang dikenali sebagai TypedQuery. Perkara ini selalu disukai sekiranya kita mengetahui jenis hasil Pertanyaan kita terlebih dahulu. Selain itu, ia menjadikan kod kami lebih dipercayai dan lebih mudah untuk diuji.

Mari lihat alternatif TypedQuery , berbanding contoh pertama kami:

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, kita dapat menaip lebih kuat secara percuma, mengelakkan kemungkinan pengecualian membuang di jalan raya.

3.2. DinamakanQuery

Walaupun kita dapat mendefinisikan Query secara dinamis mengenai kaedah tertentu, mereka akhirnya dapat berkembang menjadi basis kod yang sukar dijaga. Bagaimana jika kita dapat menyimpan pertanyaan penggunaan umum di satu tempat yang terpusat dan mudah dibaca?

JPA juga membuat kami membahas perkara ini dengan sub-jenis Query lain yang dikenali sebagai NamedQuery.

Kami menentukan NamedQuery pada kelas Entity itu sendiri, menyediakan cara terpusat, cepat dan mudah untuk membaca dan mencari pertanyaan berkaitan Entity .

Semua NamedQueries mesti mempunyai nama yang unik.

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

@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 anotasi perlu dikumpulkan dalam sebuah @NamedQueries anotasi jika kita menggunakan Java sebelum versi 8. Dari Java 8 ke hadapan, kita hanya boleh mengulangi @NamedQuery anotasi pada kami Entity kelas.

Menggunakan NamedQuery sangat mudah:

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

4. NativeQuery

A NativeQuery hanya pertanyaan SQL. Ini membolehkan kami melepaskan kekuatan penuh pangkalan data kami, kerana kami dapat menggunakan ciri proprietari yang tidak tersedia dalam sintaks larangan JPQL.

Ini memerlukan kos. Kami kehilangan kemudahan pangkalan data aplikasi kami dengan NativeQuery kerana penyedia JPA kami tidak dapat mengaburkan butiran khusus dari pelaksanaan pangkalan data atau vendor lagi.

Mari lihat bagaimana menggunakan NativeQuery yang memberikan hasil yang sama seperti contoh sebelumnya:

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

Kita mesti selalu mempertimbangkan jika NativeQuery adalah satu-satunya pilihan. Selalunya, Query JPQL yang baik dapat memenuhi keperluan kita dan yang paling penting, mengekalkan tahap pengabaian dari pelaksanaan pangkalan data yang sebenarnya.

Menggunakan NativeQuery tidak semestinya mengunci diri kita pada satu vendor pangkalan data tertentu. Bagaimanapun, jika pertanyaan kami tidak menggunakan perintah SQL proprietari dan hanya menggunakan sintaks SQL standard, penyedia beralih tidak seharusnya menjadi masalah.

5. Pertanyaan API Kriteria

Pertanyaan API Kriteria adalah pertanyaan yang dibuat secara teratur dan selamat untuk jenis - agak serupa dengan pertanyaan 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; }

Adalah sangat menakutkan untuk menggunakan pertanyaan Kriteria API secara langsung, tetapi mereka boleh menjadi pilihan tepat ketika kita perlu menambahkan elemen pertanyaan dinamik atau ketika digabungkan dengan JPA Metamodel .

6. Kesimpulannya

Dalam artikel ringkas ini, kami mengetahui apa itu Pertanyaan JPA, bersama dengan penggunaannya.

Pertanyaan JPA adalah kaedah terbaik untuk mengaburkan logik perniagaan kami dari lapisan akses data kami kerana kami boleh bergantung pada sintaks JPQL dan membiarkan penyedia pilihan JPA kami menangani terjemahan Pertanyaan .

Semua kod yang disajikan dalam artikel ini boleh didapati di GitHub.