مقدمة
الطلاب الذين استخدموا بيانات SPRING DATA JPA واضحة جدًا أنه لا يزال من المعقد للغاية معالجة استعلامات SQL المعقدة ، ويتم استخدام QueryDSL في هذه المقالة لتبسيط عمليات JPA.
يحدد QueryDSL بناء جملة نوع ثابت شائع الاستخدام للاستعلام عن بيانات نموذج المجال المستمر. JDO و JPA هي تقنيات التكامل الرئيسية لـ QueryDSL. تهدف هذه المقالة إلى شرح كيفية استخدام QueryDSL مع JPA. JPA's QueryDSL هو بديل لاستفسارات JPQL والمعايير. QueryDSL هو مجرد إطار عمل للاستعلام العام الذي يركز على بناء استعلامات SQL الآمنة من خلال Java API.
لاستخدام QueryDSL ، هناك حاجة إلى عمليتين من المتطلبات الأساسية:
1. إضافة تبعيات إلى ملف POM
<!-Query DSL-> <redency> <roupiD> com.querydsl </rougeid> <StifactId> QueryDSL-JPA </shintifactid> </sependency> <reperency> <rougid> com.querydsl </rougiD>
2. أضف المكون الإضافي للتجميع إلى ملف POM
<Plugin> <roupiD> com.mysema.maven </groupId> <StifactId> apt-maven-plugin </artifactId> <sored> 1.1.3 </version> <evelopments> <evengution> <irod> العملية </الهدف> </الأهداف> <Corder> com.querydsl.apt.jpa.jpaannotationprocessor </processor> </ispicturation> </evention> </exjustions> </sultwin>
يبحث المكون الإضافي عن أنواع النطاق المشروح بـ javax.persistence.entity ويولد أنواع الاستعلام المقابلة لهم. فيما يلي فئة كيان المستخدم لتوضيحها ، وأنواع الاستعلام التي تم إنشاؤها هي كما يلي:
حزمة com.chhliu.springboot.jpa.entity ؛ استيراد static com.querydsl.core.types.pathmetadatafactory.*؛ استيراد com.querydsl.core.types.dsl.*؛ استيراد com.querydsl.core.types.pathmetadata ؛ استيراد javax.annotation.generated ؛ استيراد com.querydsl.core.types.path ؛ / ** * QUSER هو نوع استعلام QUERYDSL للمستخدم */ generated ("com.querydsl.codegen.entitySerializer") Quser الفئة العامة يمتد EntityPathBase <Sether> {private Static Final Long SerialVersionuid = 1153899872L ؛ مستخدم QUSER النهائي الثابت = QUSER جديد ("مستخدم") ؛ عنوان السلسلة النهائية العامة = CreateString ("العنوان") ؛ Public Final NumberPath <integer> Age = CreateNumber ("Age" ، integer.class) ؛ Public Final NumberPath <integer> id = createNumber ("id" ، integer.class) ؛ اسم السلسلة النهائية العامة = createString ("الاسم") ؛ public quser (متغير سلسلة) {super (user.class ، forvariable (متغير)) ؛ ) ) }} بعد أن أنشأنا فئة الكيان ، ثم قم بتشغيل الأمر MVN Clean Compli ، وسيكون ذلك
<DountedDirectory> الهدف/المصادر المولدة/java </outputDirectory>
إنشاء نوع الاستعلام المقابل في الدليل. ثم انسخ جميع الفئات التي تم إنشاؤها إلى المشروع ، فقط قم بذلك.
الكيان المشارك في هذا المقال هو كما يلي:
حزمة com.chhliu.springboot.jpa.entity ؛ استيراد java.io.serializable ؛ استيراد javax.persistence.entity ؛ استيراد javax.persistence.generatedValue ؛ استيراد javax.persistence.generationtype ؛ استيراد javax.persistence.id ؛ استيراد javax.persistence.table ؛ entitytable (name = "t_user") يقوم مستخدم الفئة العامة بتنفيذ serializable { / ** * * / private static final long serialversionuid = 1l ؛ ID () generatedValue (الاستراتيجية = GenerationType.auto) private int id ؛ اسم السلسلة الخاصة ؛ عنوان السلسلة الخاص ؛ عصر INT الخاص ؛ ................................................................................................................................................................................................................................................................................................................................................... }}يستخدم فئة الكيان أعلاه بشكل أساسي لعمليات الجدول الفردي.
حزمة com.chhliu.springboot.jpa.entity ؛ استيراد javax.persistence.cascadetype ؛ استيراد javax.persistence.entity ؛ استيراد javax.persistence.generatedValue ؛ استيراد javax.persistence.id ؛ استيراد javax.persistence.onetoone ؛ استيراد javax.persistence.table ؛ / ** * الوصف: toDo * author chhliu */ entity @table (name = "person") public class person {idgeneratedValue private integer id ؛ اسم السلسلة الخاصة ؛ عنوان السلسلة الخاص ؛ onetoOne (mappedby = "person" ، cascade = {cascadetype.persist ، cascadetype.remove ، cascadetype.merge}) iDcard private ؛ ......................................................................................................................................................................................................................................................................................................................... }} حزمة com.chhliu.springboot.jpa.entity ؛ استيراد javax.persistence.cascadetype ؛ استيراد javax.persistence.entity ؛ استيراد javax.persistence.fetchtype ؛ استيراد javax.persistence.generatedValue ؛ استيراد javax.persistence.id ؛ استيراد javax.persistence.onetoone ؛ استيراد javax.persistence.table ؛ / ** * الوصف: * author chhliu */ entity @table (name = "idcard") الفئة العامة idcard {idgeneratedValue private integer id ؛ سلسلة خاصة idno ؛ onetoOne (cascade = {cascadetype.merge ، cascadetype.remove ، cascadetype.persist} ، fetch = fetchtype.eager) شخص خاص ؛ ................................................................................................................................................................................................................................................................................................. }}يستخدم الكيان أعلاه بشكل رئيسي على سبيل المثال عمليات العلاقات الفردية
حزمة com.chhliu.springboot.jpa.entity ؛ استيراد java.util.list ؛ استيراد javax.persistence.cascadetype ؛ استيراد javax.persistence.column ؛ استيراد javax.persistence.entity ؛ استيراد javax.persistence.fetchtype ؛ استيراد javax.persistence.generatedValue ؛ استيراد javax.persistence.id ؛ استيراد javax.persistence.onetomany ؛ استيراد javax.persistence.table ؛ / *** الوصف: order ictity class* author chhliu*/ entitytable (name = "order_c") Order order {idgeneratedValueColumn (name = "id") private Integer ID ؛ column (length = 20 ، name = "order_name") private string ordername ؛ column (name = "count") عدد عدد صحيح خاص ؛ onetomany (mappedby = "order" ، cascade = {cascadetype.persist ، cascadetype.remove} ، fetch = betchtype.eager) قائمة خاصة <SrideItem> OrderItems ؛ ……… حذف getter ، طريقة setter ……} حزمة com.chhliu.springboot.jpa.entity ؛ استيراد javax.persistence.cascadetype ؛ استيراد javax.persistence.column ؛ استيراد javax.persistence.entity ؛ استيراد javax.persistence.fetchtype ؛ استيراد javax.persistence.generatedValue ؛ استيراد javax.persistence.id ؛ استيراد javax.persistence.joincolumn ؛ استيراد javax.persistence.manyToone ؛ استيراد javax.persistence.table ؛ / *** الوصف: OrderItem Entity Class* Auuthor Chhliu*/ entity @table (name = "order_item") class public orderitem {idgeneratedValueColumn (name = "id" ، nullable = false) INTEGER ID ؛ column (name = "item_name" ، length = 20) سلسلة itemname الخاصة ؛ column (name = "price") سعر عدد صحيح خاص ؛ ManyToOne (cascade = {cascadetype.persist ، cascadetype.remove ، cascadetype.merge} ، fetch = fetchtype.eager) joincolumn (name = "order_id") ترتيب خاص ؛ ............................................................................................................... يتم استخدام الكيان المذكوران أعلاه لإظهار عمليات مثال لعلاقة واحدة.
أولاً ، دعونا نلقي نظرة على تشغيل الجدول الواحد
1. استخدم بيانات الربيع JPA
لاستخدام وظيفة QueryDSL التي توفرها SPRING DATA JPA ، إنها بسيطة للغاية ، فقط ترث الواجهة مباشرة. يوفر Dring Data JPA واجهة QueryDSLPredicateExecutor ، والتي يتم استخدامها لدعم واجهة تشغيل استعلام QueryDSL ، على النحو التالي:
حزمة com.chhliu.springboot.jpa.repository ؛ استيراد org.springframework.data.jpa.repository.jparepository ؛ استيراد org.springframework.data.querydsl.querydslpredicateExecutor ؛ استيراد com.chhliu.springboot.jpa.entity.user ؛ الواجهة العامة userrepositorydls يمتد jParePository <user ، integer> ، querydslpredicateExecutor <Ser> {// interitance interface}توفر واجهة QueryDSLPredicateExecutor الطرق التالية:
الواجهة العامة QueryDslpredicateExecutor <T> {t findone (تنبؤات مسند) ؛ ITERBILE <T> Findall (Predicate Preprict ، sort sort) ؛ Itelfable <T> bindall (تنبؤات مسند ، orderspecifier <؟> ... الطلبات) ؛ Itelfable <T> bindall (OrderSpecifier <؟> ... الطلبات) ؛ صفحة <T> findall (تنبؤات مسند ، قابلة للباحة قابلة للباحة) ؛ العد الطويل (المتوقع المسند) ؛ منطقية موجود (أصدر المسند) ؛ } يشبه استخدام الطريقة أعلاه طرق استخدام الواجهة الأخرى في بيانات الربيع JPA. للحصول على تفاصيل ، يرجى الرجوع إلى: http://www.vevb.com/article/137757.htm
الاختبارات هي كما يلي:
المستخدم العام FindUserByUserName (اسم المستخدم النهائي) { / ** * هذا المثال هو استخدام Spring Data QueryDsl لتنفيذ * / Quser Quser = quser.user ؛ مسند مسند = quser.name.eq (اسم المستخدم) ؛ // وفقًا لاسم المستخدم ، استعبر على جدول إرجاع جدول المستخدم. findone (مسند) ؛ }SQL المقابل كما يلي:
نسخة الكود كما يلي: حدد user0_.id as id1_5_ ، user0_.address as address2_5_ ، user0_.age as age3_5_ ، user0_.name as name4_5_ from t_user user0_ where user0_name =؟
رمز مثال تشغيل الجدول الواحد كما يلي:
حزمة com.chhliu.springboot.jpa.repository ؛ استيراد java.util.list ؛ استيراد javax.persistence.entityManager ؛ استيراد javax.persistence.persistenceContext ؛ استيراد javax.persistence.query ؛ استيراد javax.transaction.transactional ؛ استيراد org.springframework.beans.factory.annotation.autowired ؛ استيراد org.springframework.data.domain.pagerequest ؛ استيراد org.springframework.data.domain.sort ؛ استيراد org.springframework.steretype.component ؛ استيراد com.chhliu.springboot.jpa.entity.quser ؛ استيراد com.chhliu.springboot.jpa.entity.user ؛ استيراد com.querydsl.core.types.predicate ؛ استيراد com.querydsl.jpa.impl.jpaqueryfactory ؛ / ** * الوصف: querydsl jpa * author chhliu */ @componenttransactional الفئة العامة userrepositorymanagerDsl {autowired private userrepositorydls ؛ @autowiredpersistenceContext private entityManager entityManager ؛ queryfactory الخاص jpaqueryfactory ؛ postconstruct public void init () {QueryFactory = new JPaqueryFactory (entityManager) ؛ } المستخدم العام FindUserByUserName (اسم المستخدم النهائي) { / ** * هذا المثال هو استخدام Spring Data QueryDsl لتنفيذ * / Quser Quser = quser.user ؛ Predicate Preprict = quser.name.eq (اسم المستخدم) ؛ مستودع الإرجاع. findone (مسند) ؛ } / *** الانتباه:* التفاصيل: الاستعلام عن جميع السجلات في جدول المستخدم* / القائمة العامة <Sether> findall () {quser quser = quser.user ؛ return queryfactory.selectfrom (Quser) .fetch () ؛ } / *** التفاصيل: استعلام أحادي الشرط* / المستخدم العام findoneByuserName (اسم المستخدم النهائي) {quser quser = quser.user ؛ return queryfactory.selectfrom (Quser). where (quser.name.eq (username)) .fetchone () ؛ } / *** التفاصيل: الجدول الفردي متعدد الإجراءات التعليمية* / المستخدم العام findonebyusernameanddress (اسم مستخدم السلسلة النهائية ، عنوان السلسلة النهائية) {Quser Quser = quser.user ؛ return queryfactory.select (QUSER). من (QUSER) // الجملتين أعلاه تعادل SELECTFROM. where (quser.name.eq (اسم المستخدم). و (quser.address.eq (العنوان))) .fetchone () ؛ } / *** التفاصيل: استخدم Join Query* / قائمة عامة <Sether> FindUsersByjoin () {Quser Quser = quser.user ؛ username Quser = Quser جديد ("الاسم") ؛ return queryfactory.selectfrom (Quser) .innerjoin (Quser) .on (quser.id.intvalue (). Eq (username.id.intvalue ())) .fetch () ؛ } / ** * التفاصيل: فرز نتائج الاستعلام * / قائمة عامة <Sether> findUserandorder () {Quser Quser = quser.user ؛ return queryfactory.selectfrom (Quser) .orderby (quser.id.desc ()) .fetch () ؛ } / ** * التفاصيل: المجموعة باستخدام * / قائمة عامة <string> findUserByGroup () {Quser Quser = quser.user ؛ return queryfactory.select (quser.name). من (Quser) .groupby (quser.name) .fetch () ؛ } / *** التفاصيل: حذف المستخدم* / public long deleteuser (string username) {quser quser = quser.user ؛ return queryfactory.delete (Quser). where (quser.name.eq (username)). execute () ؛ } / *** التفاصيل: قم بتحديث السجل* / public updateUser (المستخدم النهائي U ، اسم المستخدم النهائي) {quser quser = quser.user ؛ return queryfactory.update (Quser). where (quser.name.eq (username)). } / ** * التفاصيل: استخدم الاستعلام الأصلي * / المستخدم العام FindOnuserByoriginalsQl (اسم المستخدم النهائي) {Quser Quser = quser.user ؛ استعلام Query = QueryFactory.SelectFrom (Quser). where (quser.name.eq (username)). createequery () ؛ إرجاع (المستخدم) Query.GetSingleresult () ؛ } / *** التفاصيل: Query Query Table Single* / Public Page <Sether> findallandpager (إزاحة int النهائية ، pagesize النهائي) {estective = quser.user.id.lt (10) ؛ sort sort = new sort (new sort.order (sort.direction.desc ، "id")) ؛ pagerequest pr = new pagerequest (الإزاحة ، pagesize ، النوع) ؛ Return Respository.Findall (المسند ، PR) ؛ }}أمثلة التشغيل متعددة الطاولة (واحد إلى واحد) هي كما يلي:
حزمة com.chhliu.springboot.jpa.repository ؛ استيراد java.util.arraylist ؛ استيراد java.util.list ؛ استيراد javax.annotation.postconstruct ؛ استيراد javax.persistence.entityManager ؛ استيراد javax.persistence.persistenceContext ؛ استيراد org.springframework.beans.factory.annotation.autowired ؛ استيراد org.springframework.stereotype.component ؛ استيراد com.chhliu.springboot.jpa.dto.personidcarddto ؛ استيراد com.chhliu.springboot.jpa.entity.qidcard ؛ استيراد com.chhliu.springboot.jpa.entity.qidcard ؛ استيراد com.chhliu.springboot.jpa.entity.qperson ؛ استيراد com.querydsl.core.queryResults ؛ استيراد com.querydsl.core.tuple ؛ استيراد com.querydsl.core.types.predicate ؛ استيراد com.querydsl.jpa.impl.jpaquery ؛ استيراد com.querydsl.jpa.impl.jpaqueryfactory ؛ Component public class personandidCardManager {AuutOwiredPersistenceContext private entityManager entityManager ؛ queryfactory الخاص jpaqueryfactory ؛ postconstruct public void init () {QueryFactory = new JPaqueryFactory (entityManager) ؛ } / *** التفاصيل: استعلام ديناميكي متعدد الطاولة* / قائمة عامة <Tuple> bindallpersonandidcard () {prosticate estive = (qperson.person.id.intvalue ()). jpaquery <Tuple> jpaquery = queryfactory.select (qidcard.idcard.idno ، qperson.person.address ، qperson.person.name). من (qidcard.idcard ، qperson.person). إرجاع jpaquery.fetch () ؛ } / *** التفاصيل: ينتج عن استعلام الإخراج في قائمة DTO* / Public List <PersonIdCardDTo> findBydto () {prosticate predict = (qperson.person.id.intvalue ()). jpaquery <Tuple> jpaquery = queryfactory.select (qidcard.idcard.idno ، qperson.person.address ، qperson.person.name). من (qidcard.idcard ، qperson.person). قائمة <Tuple> tuples = jpaquery.fetch () ؛ قائمة <PersonIdCardDto> dtos = new ArrayList <PersonIdCardDTo> () ؛ if (null! = tuples &&! tuples.isempty ()) {for (tuple tuple: tuples) {string address = tuple.get (qperson.person.address) ؛ اسم السلسلة = tuple.get (qperson.person.name) ؛ string idcard = tuple.get (qidcard.idcard.idno) ؛ PersonIdCardDTO DTO = New PersonIdCardDTO () ؛ dto.setaddress (العنوان) ؛ dto.setidno (idcard) ؛ dto.setName (الاسم) ؛ dtos.add (dto) ؛ }} return dtos ؛ } / *** التفاصيل: استعلام ديناميكي متعدد الطاولة وتوصل إلى تراجع* / QueryResults <Tuple> findBydToAndPager (int industse ، int pagesize) {est estericate = (qperson.person.id.intvalue ()). return queryfactory.select (qidcard.idcard.idno ، qperson.person.address ، qperson.person.name). من (qidcard.idcard ، qperson.person). where (predicate) .Offset (Offset) .Limit (pagesizeize) .fetchResults () ؛ }}في المثال أعلاه حيث يتم إخراج نتائج الاستعلام في وضع DTO ، بعد الانتهاء من الاستعلام ، يتم تحويل نتائج الاستعلام يدويًا إلى كائنات DTO. هذه الطريقة ليست أنيقة للغاية. يوفر لنا QueryDSL طريقة أفضل ، انظر المثال التالي:
/ *** التفاصيل: الطريقة 1: استخدم Bean Projection*/ Public List <PersonIdCardDTo> findByDtouseBean () {pestection estive = (qperson.person.id.intvalue ()). return queryfactory.select (profelss.bean (personidcarddto.class ، qidcard.idcard.idno ، qperson.person.address ، qperson.person.name)) .from (qidcard.idcard ، qperson.person) .where (stest) .fetch () ؛ } / ** * التفاصيل: الطريقة 2: استخدم الحقول بدلاً من Setter * / List Public <PersonIdCardDTo> findbydtousefields () {proseCate preprice = (qperson.person.id.intvalue ()). eq (qidcard.idcard.person.id.intvalue ()) ؛ return queryfactory.select (DespsideS.Fields (PersonIdCarddto.Class ، qidcard.idcard.idno ، qperson.person.address ، qperson.person.name)) .from (qidcard.idcard ، qperson.person). where (predate) .fetch () ؛ } / *** التفاصيل: الطريقة 3: استخدم طريقة المنشئ ، لاحظ أن ترتيب السمات في المُنشئ يجب أن يكون متسقًا مع الترتيب في المُنشئ* / القائمة العامة <PersonIdCardDTo> findbydtouseConstructor () {predict = (qperson.person.id.intvalue ()). return queryfactory.select (DesproveneS.Constructor (PersonIdCarddto.class ، qperson.person.name ، qperson.person.address ، qidcard.idcard.idno)). من (qidcard.idcard ، qperson.person). } ما سبق يوفر فقط العديد من الأفكار. بالطبع ، يمكنك أيضًا استخدام @QueryProjection لتنفيذها ، وهو مرن للغاية.
مثال واحد إلى الرجل:
حزمة com.chhliu.springboot.jpa.repository ؛ استيراد java.util.list ؛ استيراد javax.annotation.postconstruct ؛ استيراد javax.persistence.entityManager ؛ استيراد javax.persistence.persistenceContext ؛ استيراد org.springframework.beans.factory.annotation.autowired ؛ استيراد org.springframework.stereotype.component ؛ استيراد com.chhliu.springboot.jpa.entity.qorder ؛ استيراد com.chhliu.springboot.jpa.entity.qorderItem ؛ استيراد com.querydsl.core.tuple ؛ استيراد com.querydsl.core.types.predicate ؛ استيراد com.querydsl.jpa.impl.jpaquery ؛ استيراد com.querydsl.jpa.impl.jpaqueryfactory ؛ component public orderandorderiterItemManager {autowiredpersistenceContext private entityManager entityManager ؛ queryfactory الخاص jpaqueryfactory ؛ postconstruct public void init () {QueryFactory = new JPaqueryFactory (entityManager) ؛ } /*** التفاصيل: استعلام واحد إلى رجل ، مشروط* /قائمة عامة <Tuple> findOrderandOrderItEmbyOrderName (string ordername) {// إضافة شروط الاستعلام ، مسبقًا = qorder.ordername.eq (ordername) ؛ jpaquery <Tuple> jpaquery = queryfactory.select (qorder.order ، qorderitem.orderitem). من (qorder.order ، qorderitem.orderitem). // احصل على النتيجة return jpaquery.fetch () ؛ } /*** التفاصيل: استعلام Join-Table Multi-Table* /القائمة العامة <Tuple> findallbyorderName (string ordername) {// إضافة شروط الاستعلام المسند = qorder.ordername.eq (OrderName) ؛ jpaquery <Tuple> jpaquery = queryfactory.select (qorder.order ، qorderitem.orderitem). من (qorder.order ، qorderitem.orderitem) .rightjoin (qorder.order) .on (qorderitem.orderitem.oder.id.intvalue (). jpaquery.here (مسند) ؛ // احصل على النتيجة return jpaquery.fetch () ؛ }} من المثال أعلاه ، يمكننا أن نرى أن QueryDSL قد أبسط عملياتنا إلى حد كبير
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.