Kata pengantar
Siswa yang telah menggunakan data musim semi JPA sangat jelas bahwa masih cukup rumit untuk memproses kueri SQL yang kompleks, dan QueryDSL dalam artikel ini digunakan untuk menyederhanakan operasi JPA.
QueryDSL mendefinisikan sintaks tipe statis yang umum digunakan untuk menanyakan data model domain persisten. JDO dan JPA adalah teknologi integrasi utama QueryDSL. Artikel ini bertujuan untuk menjelaskan cara menggunakan QueryDSL dalam kombinasi dengan JPA. QueryDSL JPA adalah alternatif untuk kueri JPQL dan kriteria. QueryDSL hanyalah kerangka kueri umum yang berfokus pada membangun kueri SQL yang aman jenis melalui Java API.
Untuk menggunakan querydsl, dua operasi prasyarat diperlukan:
1. Tambahkan dependensi ke file pom
<!-Query DSL-> <dependency> <GroupId> com.querydsl </groupid> <ArtifactId> querydsl-jpa </t Artifactid> </dependency> <dependency> <groupid> com.querydsl </groupid> <t ArtifactId> querydsl-tap
2. Tambahkan plug-in kompilasi ke file POM
<lugin> <GroupId> com.mysema.maven </groupid> <ArTifactId> apt-maven-plugin </arttifactid> <version> 1.1.3 </version> <Executions> <Execution> <ject> <goals> </jang> </gol <Configuration> <suxputDirectory> Target/Generasi/Generasi/Generasi/</gol/JAGERURASI> <OKURURASI> <OKURPUTRORY> <outputDirectory> <srossorsor> com.querydsl.apt.jpa.jpaannotationprocessor </socessor> </configuration> </execution> </executions> </plugin>
Plugin ini mencari tipe domain yang dianotasi dengan javax.persistence.entity dan menghasilkan jenis kueri yang sesuai untuk mereka. Berikut ini adalah kelas entitas pengguna untuk diilustrasikan, dan jenis kueri yang dihasilkan adalah sebagai berikut:
paket com.chhliu.springboot.jpa.entity; impor statis com.querydsl.core.types.pathmetadatafactory.*; impor com.querydsl.core.types.dsl.*; impor com.querydsl.core.types.pathmetadata; impor javax.annotation.generasi; impor com.querydsl.core.types.path; / ** * QUSER adalah jenis kueri QueryDSL untuk pengguna */ @Generated ("com.querydsl.codegen.entityserializer") kelas publik QUSER memperluas EntityPathBase <User> {private static long serialversionuid = 115389872L; Public Static Final Quser User = quser baru ("pengguna"); Alamat StringPath Final Publik = CreateString ("Alamat"); Publik Final NumberPath <Integer> usia = CreateNumber ("Age", Integer.class); Publik Final NumberPath <Integer> id = CreateNumber ("id", integer.class); name public final stringpath = createString ("name"); qUser publik (variabel string) {super (user.class, forvariable (variabel)); } public quser (path <? Extends user> path) {super (path.getType (), path.getMetAdata ()); } public quser (PathMetadata metadata) {super (user.class, metadata); }} Setelah kami membuat kelas entitas, lalu jalankan perintah MVN Clean Compli, dan itu akan terjadi
<OutputDirectory> Target/Sumber-Sumber/Java </OutputDirectory>
Hasilkan jenis kueri yang sesuai di direktori. Kemudian salin semua kelas yang dihasilkan ke proyek, lakukan saja.
Entitas yang terlibat dalam artikel ini adalah sebagai berikut:
paket com.chhliu.springboot.jpa.entity; impor java.io.serializable; impor javax.persistence.entity; impor javax.persistence.generatedValue; impor javax.persistence.generationType; impor javax.persistence.id; impor javax.persistence.table; @Entity @table (name = "t_user") Pengguna kelas publik mengimplementasikan serializable { / ** * * / private static final long serialVersionuid = 1l; @Id () @GeneratedValue (Strategy = GenerationType.Auto) Private InT ID; nama string pribadi; alamat string pribadi; usia int pribadi; ………… hilangkan Getter, metode setter …………/ ** * Perhatian: * Rincian: nyaman untuk melihat hasil tes * @author chhliu */ @override public string toString () {return "user [id =" + id + ", name =" + name + ", alamat =" + alamat + ", usia =" + usia + "]; }}Kelas entitas di atas terutama digunakan untuk operasi tabel tunggal.
paket com.chhliu.springboot.jpa.entity; impor javax.persistence.cascadetype; impor javax.persistence.entity; impor javax.persistence.generatedValue; impor javax.persistence.id; impor javax.persistence.onetoone; impor javax.persistence.table; / ** * Deskripsi: TODO * @Author chhliu */ @entity @table (name = "person") orang kelas publik {@id @generatedValue Private Integer ID; nama string pribadi; alamat string pribadi; @OneToOne (mappedBy = "person", cascade = {cascadetype.persist, cascadetype.remove, cascadetype.merge}) idcard idcard pribadi; ………… hilangkan Getter, Metode Setter ………… @Override Public String ToString () {return "Person [id =" + id + ", name =" + name + ", address =" + address + ", idCard =" + idCard + "]"; }} paket com.chhliu.springboot.jpa.entity; impor javax.persistence.cascadetype; impor javax.persistence.entity; impor javax.persistence.fetchType; impor javax.persistence.generatedValue; impor javax.persistence.id; impor javax.persistence.onetoone; impor javax.persistence.table; / ** * Deskripsi: * @author chhliu */ @entity @table (name = "idcard") IDCard kelas publik {@id @generatedValue Private Integer ID; private string idno; @Onetoone (cascade = {cascadetype.merge, cascadetype.remove, cascadetype.persist}, fetch = fetchType.eager) orang pribadi; ………… oloskan Getter, Metode Setter ………… @Override Public String ToString () {return "idCard [id =" + id + ", idno =" + idno + ", person =" + person + "]"; }}Dua entitas di atas terutama digunakan misalnya operasi hubungan satu-ke-satu
paket com.chhliu.springboot.jpa.entity; impor java.util.list; impor javax.persistence.cascadetype; impor javax.persistence.column; impor javax.persistence.entity; impor javax.persistence.fetchType; impor javax.persistence.generatedValue; impor javax.persistence.id; impor javax.persistence.onetomany; impor javax.persistence.table; / *** Deskripsi: kelas entitas pesanan* @author chhliu*/ @entity @table (name = "order_c") pesanan kelas publik {@id @generatedvalue @column (name = "id") private integer id; @Column (length = 20, name = "order_name") private string ordername; @Column (name = "count") Private Integer Count; @Onetomany (mappedby = "order", cascade = {cascadetype.persist, cascadetype.remove}, fetch = fetchType.eager) Daftar pribadi <Fertionem> orderitem; ……… hilangkan Getter, Metode Setter ……} paket com.chhliu.springboot.jpa.entity; impor javax.persistence.cascadetype; impor javax.persistence.column; impor javax.persistence.entity; impor javax.persistence.fetchType; impor javax.persistence.generatedValue; impor javax.persistence.id; impor javax.persistence.joincolumn; impor javax.persistence.manytoone; impor javax.persistence.table; / *** Deskripsi: kelas entitas orderitem* @author chhliu*/ @entity @table (name = "order_item") kelas publik orderitem {@id @generatedValue @column (name = "id", nullable = false) Private Integer ID; @Column (name = "item_name", length = 20) Private String itemName; @Column (name = "Price") Private Integer Price; @ManytoOne (cascade = {cascadetype.persist, cascadetype.remove, cascadetype.merge}, fetch = fetchType.eAger) @joincolumn (name = "order_id") pesanan pribadi; ………… hilangkan Getter, metode setter ………} Dua entitas di atas digunakan untuk menunjukkan contoh operasi hubungan satu-ke-banyak.
Pertama, mari kita lihat operasi tabel tunggal
1. Gunakan data pegas JPA
Untuk menggunakan fungsi QueryDSL yang disediakan oleh Spring Data JPA, ini sangat sederhana, cukup mewarisi antarmuka secara langsung. Data Spring JPA menyediakan antarmuka QueryDSlPredicateExecutor, yang digunakan untuk mendukung antarmuka operasi kueri kueryDSL, sebagai berikut:
paket com.chhliu.springboot.jpa.repository; impor org.springframework.data.jpa.repository.jparepository; impor org.springframework.data.querydsl.querydslPredicateExecutor; impor com.chhliu.springboot.jpa.entity.user; Antarmuka Publik UserRepositoryDls Memperluas JParePository <User, Integer>, QueryDSlPredicateExecutor <User> {// Antarmuka warisan}Antarmuka QueryDSlPredicateExecutor menyediakan metode berikut:
querydslPredicateExecutor antarmuka publik <T> {t findOne (predikat prediksi); Iterable <T> findAll (predikat prediksi, sortir sortir); Iterable <t> findAll (predicate predict, orderspecifier <?> ... pesanan); Iterable <t> findAll (orderspecifier <?> ... pesanan); Halaman <T> FindAll (Predicate Predict, Pagable Pagable); jumlah panjang (predikat prediksi); ada boolean (predikat predikat); } Penggunaan metode di atas mirip dengan metode penggunaan antarmuka lainnya dalam data pegas JPA. Untuk detailnya, silakan merujuk ke: http://www.vevb.com/article/137757.htm
Tesnya adalah sebagai berikut:
Pengguna publik FindUserByUserName (Final String username) { / ** * Contoh ini adalah menggunakan spring data querydsl untuk mengimplementasikan * / quser quser = quser.user; Predikat predikat = qUser.name.eq (nama pengguna); // Menurut nama pengguna, permintaan tabel pengguna mengembalikan repository.findOne (predikat); }SQL yang sesuai adalah sebagai berikut:
Salinan kode adalah sebagai berikut: Pilih user0_.id sebagai id1_5_, user0_.address sebagai alamat2_5_, user0_.age as Age3_5_, user0_.name sebagai name4_5_ dari t_user user0_ di mana user0_.name =?
Kode contoh operasi tabel tunggal adalah sebagai berikut:
paket com.chhliu.springboot.jpa.repository; impor java.util.list; impor javax.persistence.entityManager; impor javax.persistence.persistenceContext; impor javax.persistence.query; impor javax.transaction.transactional; impor org.springframework.beans.factory.annotation.Autowired; impor org.springframework.data.domain.pagerequest; impor org.springframework.data.domain.sort; impor org.springframework.steretype.component; impor com.chhliu.springboot.jpa.entity.quser; impor com.chhliu.springboot.jpa.entity.user; impor com.querydsl.core.types.predicate; impor com.querydsl.jpa.impl.jpaqueryfactory; / ** * Deskripsi: querydsl jpa * @author chhliu */ @component @transactional Public Class userrepositoryManagersl {@autowired private userrepositoryDls repository; @Autowired @PersistenceContext Private EntityManager EntityManager; queryfactory jpaqueryfactory pribadi; @PostConstruct public void init () {queryFactory = jpaqueryFactory baru (EntityManager); } pengguna publik findUserByUserName (final string username) { / ** * Contoh ini adalah menggunakan data spring querydsl untuk mengimplementasikan * / quser quser = quser.user; Predikat prediksi = quser.name.eq (nama pengguna); return repository.findOne (predikat); } / *** Perhatian:* Detail: Permintaan semua catatan di tabel pengguna* / Daftar publik <user> findAll () {quser quser = quser.user; return queryfactory.selectfrom (quser) .fetch (); } / *** Detail: Kueri Kondisi Tunggal* / Pengguna Publik FindOneSerName (Final String UserName) {Quser quser = quser.user; return queryfactory.selectfrom (quser) .where (quser.name.eq (nama pengguna)) .fetchone (); } / *** Detail: Tabel tunggal kueri multi-kondisi* / pengguna publik findOneSerNeMandDaddress (nama pengguna string akhir, alamat string akhir) {quser quser = quser.user; return queryfactory.select (quser) .from (quser) // Dua kalimat di atas setara dengan SelectFrom. Di mana (quser.name.eq (nama pengguna) .and (quser.address.eq (alamat))) // Kode ini setara dengan di mana (quser.name.eq (USERN (USERN (USERN (USERN (USERAC.), ubuse.ADQ.ADRESS (ubuser. .fetchone (); } / *** Detail: Gunakan query gabungan* / daftar publik <user> findUsersByJoin () {quser quser = quser.user; Quser username = quser baru ("name"); return queryfactory.selectfrom (quser) .innerjoin (quser) .on (quser.id.intvalue (). eq (username.id.intvalue ())) .fetch (); } / ** * Rincian: Urutkan hasil kueri * / Daftar publik <User> findUserAndOrder () {quser quser = quser.user; return queryfactory.selectfrom (quser) .orderby (quser.id.desc ()) .fetch (); } / ** * Detail: grup dengan menggunakan * / daftar publik <string> findUserByGroup () {quser quser = quser.user; return queryfactory.select (quser.name) .from (quser) .groupby (quser.name) .fetch (); } / *** Detail: Hapus pengguna* / public long deleteUser (string username) {quser quser = quser.user; return queryfactory.delete (quser) .where (quser.name.eq (username)). execute (); } / *** Detail: Perbarui catatan* / Public Long UpdateAser (pengguna akhir U, final string username) {quser quser = quser.user; kembalikan queryfactory.update (quser) .where (quser.name.eq (username)) .set (quser.name, u.getname ()) .set (quser.age, u.getage ()) .set (quser.address, u.getAddress (). Eksecute (); } / ** * Detail: Gunakan kueri asli * / pengguna publik findOneSerbyoriginalsql (final string username) {quser quser = quser.user; Kueri kueri = queryfactory.selectfrom (quser) .where (quser.name.eq (nama pengguna)). Createqueery (); return (user) query.getsingleresult (); } / *** Rincian: Pagination Query Tabel Tunggal* / Halaman Publik <User> findAllIndPager (final int offset, final int pageSize) {predicate predicate = quser.user.id.lt (10); Sort sort = new sort (new sort.order (sort.direction.desc, "id")); PageRequest PR = PageRequest baru (Offset, PageSize, Sort); return repository.findall (predikat, pr); }}Contoh operasi multi-meja (satu-ke-satu) adalah sebagai berikut:
paket com.chhliu.springboot.jpa.repository; impor java.util.arraylist; impor java.util.list; impor javax.annotation.postconstruct; impor javax.persistence.entityManager; impor javax.persistence.persistenceContext; impor org.springframework.beans.factory.annotation.Autowired; impor org.springframework.stereotype.component; impor com.chhliu.springboot.jpa.dto.personidcarddto; impor com.chhliu.springboot.jpa.entity.qidcard; impor com.chhliu.springboot.jpa.entity.qidcard; impor com.chhliu.springboot.jpa.entity.qperson; impor com.querydsl.core.queryResults; impor com.querydsl.core.tuple; impor com.querydsl.core.types.predicate; impor com.querydsl.jpa.impl.jpaquery; impor com.querydsl.jpa.impl.jpaqueryfactory; @Component kelas publik personandidcardManager {@autowired @PersistenceContext private EntityManager EntityManager; queryfactory jpaqueryfactory pribadi; @PostConstruct public void init () {queryFactory = jpaqueryFactory baru (EntityManager); } / *** Rincian: Multi-Table Dynamic Query* / Daftar Publik <Tuple> findAllPersonAndIdCard () {predicate predicate = (qperson.person.id.intvalue ()). EQ (qidcard.idcard.person.id.intvalue ()); JpaQuery <Eple> jpaquery = queryfactory.select (qidcard.idcard.idno, qperson.person.address, qperson.person.name) .drom (qidcard.idcard, qperson.person). Mana (predikat); return jpaquery.fetch (); } / *** Rincian: output kueri menghasilkan DTO* / Daftar publik <SonidCardDto> findBydto () {predicate prededic = (qperson.person.id.intvalue ()). EQ (qidcard.idcard.person.id.intvalue ()); JpaQuery <Eple> jpaquery = queryfactory.select (qidcard.idcard.idno, qperson.person.address, qperson.person.name) .drom (qidcard.idcard, qperson.person). Mana (predikat); Daftar <Tuple> tuples = jpaquery.fetch (); Daftar <SonidCardDto> dtos = new ArrayList <SonidCardDto> (); if (null! = tuples &&! tuples.isempty ()) {for (tuple tuple: tuples) {string address = tuple.get (qperson.person.address); Name string = tuple.get (qperson.person.name); String idcard = tuple.get (qidcard.idcard.idno); Personidcarddto dto = new personidcarddto (); dto.setAddress (alamat); dto.setidno (idcard); dto.setname (nama); dtos.add (dto); }} return dtos; } / *** Detail: Multi-Table Dynamic Query and Pagination* / Public QueryResults <Tuple> findByDtoAndPager (int offset, int pageSize) {predicate predicate = (qperson.person.id.intvalue ()). EQ (qidcard.idcard.person.idvale ()). EQ (qidcard.idcard.person.IdVue () (). return queryfactory.select (qidcard.idcard.idno, qperson.person.address, qperson.person.name) .from (qidcard.idcard, qperson.person). mana (predikat) .offset (offset) .Limit (halaman) .fetchResults (); }}Dalam contoh di atas di mana hasil kueri output dalam mode DTO, setelah kueri selesai, hasil kueri secara manual dikonversi menjadi objek DTO. Metode ini sebenarnya tidak terlalu elegan. QueryDSL memberi kita cara yang lebih baik, lihat contoh berikut:
/ *** Detail: Metode 1: Gunakan proyeksi kacang*/ Daftar publik <sonidcarddto> findByDtouseBean () {predicate predicate = (qperson.person.id.intvalue ()). Eq (qidcard.idcard.person.id.intvalue ()); return queryfactory.select (proyections.bean (personidcarddto.class, qidcard.idcard.idno, qperson.person.address, qperson.person.name)) .from (qidcard.idcard, qperson.person). Di mana (predikat) .fetch (); } / ** * Rincian: Metode 2: Gunakan bidang alih -alih setter * / Daftar publik <sonidcarddto> findByDtouseFields () {predicate prededity = (qperson.person.id.intvalue ()). Eq (qidcard.idcard.person.id.intvalue ()); return queryfactory.select (proyections.fields (personidcarddto.class, qidcard.idcard.idno, qperson.person.address, qperson.person.name)) .from (qidcard.idcard, qperson.person). Di mana (predikat) .fetch (); } / *** Rincian: Metode 3: Gunakan metode konstruktor, perhatikan bahwa urutan atribut dalam konstruktor harus konsisten dengan urutan dalam konstruktor* / daftar publik <sonidcarddto> findBydtouseConstructor () {predicate predict = (qperson.person.id.intvalue ()). Eq (qidcard. return queryfactory.select (proyeksi.constructor (personidcarddto.class, qperson.person.name, qperson.person.address, qidcard.idcard.idno)) .from (qidcard.idcard, qperson.person). Di mana (predikat) .fetch (); } Di atas hanya memberikan beberapa ide. Tentu saja, Anda juga dapat menggunakan @QueryProyjection untuk mengimplementasikannya, yang sangat fleksibel.
Contoh satu-ke-banyak:
paket com.chhliu.springboot.jpa.repository; impor java.util.list; impor javax.annotation.postconstruct; impor javax.persistence.entityManager; impor javax.persistence.persistenceContext; impor org.springframework.beans.factory.annotation.Autowired; impor org.springframework.stereotype.component; impor com.chhliu.springboot.jpa.entity.qorder; impor com.chhliu.springboot.jpa.entity.qorderitem; impor com.querydsl.core.tuple; impor com.querydsl.core.types.predicate; impor com.querydsl.jpa.impl.jpaquery; impor com.querydsl.jpa.impl.jpaqueryfactory; @Component kelas publik OrderAndOrderTeMmanager {@Autowired @PersistenceContext Private EntityManager EntityManager; queryfactory jpaqueryfactory pribadi; @PostConstruct public void init () {queryFactory = jpaqueryFactory baru (EntityManager); } /*** Rincian: kueri satu-ke-banyak, bersyarat* /Daftar Publik <Tuple> FindOrderDoDerTerItEMByOrdName (String OrderName) {// Tambahkan Kondisi Permintaan Predikat Predikat = Qorder.order.orderName.eq (orderName); JpaQuery <Eple> jpaquery = queryfactory.select (qorder.order, qorderitem.orderItem) .from (qorder.order, qorderitem.orderitem) .where (qorderitem.orderitem.order.id.intvalue (). // dapatkan hasilnya, return jpaquery.fetch (); } /*** Detail: Multi-Table Join Query* /Daftar Publik <Tuple> findAllByOrdName (String orderName) {// Tambahkan kondisi kueri predikat predikat = qorder.order.ordername.eq (orderName); JpaQuery <Eple> jpaquery = queryfactory.select (qorder.order, qorderitem.orderItem) .from (qorder.order, qorderitem.orderitem) .rightjoin (qorder.order) .on (qorderitem.orderitem.order.id.intvalue (). jpaquery.where (predikat); // dapatkan hasilnya, return jpaquery.fetch (); }} Dari contoh di atas, kita dapat melihat bahwa querydsl telah sangat menyederhanakan operasi kami
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.