ฉันพบว่ามันยากมากที่จะยืนยันในการเขียนบล็อกและเหตุผลต่าง ๆ จะนำไปสู่ไม่จำเป็นต้องดูแลบล็อก เดิมทีฉันวางแผนที่จะเขียนการใช้งาน DIY ของ ORM และดูเวลา ฉันอยากจะใช้ SQL แบบไดนามิกก่อนและเพิ่มการใช้งานที่สมบูรณ์ของ ORM ในครั้งต่อไปที่ฉันมีเวลา
คนที่ใช้ mybatis อาจคุ้นเคยกับ SQL แบบไดนามิก หากคุณไม่ได้ใช้มันเพียงแค่ดูความสนุก ครั้งแรกที่ฉันได้ติดต่อกับ MySQL คือตอนที่ฉันอยู่ในปีสุดท้าย ในเวลานั้นฉันคิดว่า SQL แบบไดนามิกนั้นยอดเยี่ยมและยืดหยุ่นมาก ฉันอยากจะหาวิธีที่จะนำไปใช้เสมอ แม้ว่าฉันสามารถเขียน IOC, MVC และกรอบ ORM ที่เรียบง่ายในเวลานั้น (เลียนแบบ myBaits แต่ไม่มีส่วน SQL แบบไดนามิก) แต่ฉันก็ยังหาได้ว่าจะใช้ SQL แบบไดนามิกในแกนกลางของ mybatis และวิธีการใช้งานได้อย่างไร บางทีรหัสอาจพันกันเกินไปและฉันก็ไม่เข้าใจเลย จนถึงตอนนี้ฉันไม่มีความกล้าที่จะอ่านส่วน SQL แบบไดนามิกของ mybatis บางทีฉันอาจเกิดมาพร้อมกับอัลกอริทึมที่อธิบายไม่ได้
ไม่กี่ปีที่ผ่านมาเนื่องจากฉันต้องการสร้างแพลตฟอร์มการกำหนดค่าและต้องการใช้ภาษาแยกวิเคราะห์เพื่อแทนที่การใช้งาน Java ซึ่งอนุญาตให้บุคลากรกำหนดค่าสามารถเขียนรหัสจำนวนเล็กน้อยบนหน้าเพื่อใช้ตรรกะทางธุรกิจที่ซับซ้อน (รวมถึงการดำเนินการฐานข้อมูล) ในเวลานั้น Java มีเครื่องยนต์วิเคราะห์ JS อยู่แล้ว แต่คนส่วนใหญ่บอกว่าประสิทธิภาพต่ำเกินไป ถ้าฉันไม่รู้ว่าฉันคลั่งไคล้อะไรฉันก็คิดที่จะใช้ภาษาแยกวิเคราะห์ด้วยตัวเอง อย่างไรก็ตามฉันมักจะใฝ่ฝันที่จะตระหนักถึงภาษาของตัวเอง การเริ่มต้นด้วยภาษาวิเคราะห์ง่ายกว่าภาษาที่รวบรวมดังนั้นฉันจึงเริ่มทำอย่างเด็ดขาด หลังจากเขียนมันฉันรู้ว่าการใช้งานของฉันอาจไม่ได้ประสิทธิภาพเท่ากับเครื่องยนต์ JS ในเวลานั้น ในเวลานั้นฉันยังเด็กและเรียบง่าย การใช้งาน SQL แบบไดนามิกที่ฉันกำลังพูดถึงในวันนี้ได้รับแรงบันดาลใจจากภาษาการแยกวิเคราะห์ในเวลานั้น
มาพูดถึง SQL แบบไดนามิกโดยไม่พูดเรื่องไร้สาระมากนัก โปรดดูตัวอย่างต่อไปนี้ ก่อนอื่นฉันประกาศว่าตัวอย่างที่นี่ไม่ใช่วิธีที่ถูกต้องในการเขียน SQL ฉันแค่ต้องการเขียนโครงสร้างซ้อนที่ซับซ้อนที่สุดเท่าที่จะทำได้ หากสถานการณ์ที่ซับซ้อนนี้ถูกนำไปใช้ก็ยิ่งยากที่จะทำให้ง่ายขึ้น
ลบจาก pl_pagewidget <ถ้า test = "widgetCodes! = null"> โดยที่ pagewidGetCode ใน <foreach collection = "widgetCodes" item = "item" index = "index" เปิด = "(" separator = "," close = ") open = "(" separator = "," close = ")"> #{b} </foreach> </foreach> </if> <ถ้า test = "a! = null"> และ a = #{a} </if>ในการใช้ SQL สำหรับการแยกวิเคราะห์ตัวอย่างข้างต้นหนึ่งในปัญหานั้นคล้ายกับวิธีการกำหนดเงื่อนไขจริงหรือเท็จในแอตทริบิวต์การทดสอบ อย่างไรก็ตามความยากลำบากนี้อยู่ตรงหน้าการแสดงออกของ OGNL ที่เรียนรู้ใน struts2 ฉันไม่รู้ว่าเพื่อนพบปรากฏการณ์ที่ค่อนข้างแปลกนั่นคือบางครั้งการแสดงออกต่อไปนี้เขียนไว้ใน MyBatis Dynamic SQL แต่เมื่อ n = 0 มันตรงกับเงื่อนไขนั่นคือค่าในการทดสอบเป็นเท็จและ 0 ไม่สามารถปฏิบัติตามเงื่อนไขของนิพจน์นี้ได้ นี่คือเหตุผลสำหรับไลบรารี OGNL ไม่มีทางที่จะเล่นได้เช่นนี้เพียงจำไว้ว่าเป็นสถานการณ์พิเศษ
test = "n! = null และ n! = '' '
การแสดงออกของ OGNL นั้นสะดวกมากที่จะใช้ดังนี้
นำเข้า java.util.hashmap; นำเข้า java.util.map; นำเข้า ognl.ognl; คลาสสาธารณะ ognltest {// ผลลัพธ์ผลลัพธ์: โมฆะสาธารณะคงที่เท็จหลัก (สตริง [] args) โยนข้อยกเว้น {String con1 = "n! = null และ n! = '' '"; แผนที่ <string, Object> root = new hashmap <> (); root.put ("n", 0); System.out.println (ognl.getValue (con1, root)); -ในการใช้ SQL สำหรับการแยกวิเคราะห์ตัวอย่างข้างต้นความยากที่สองคือแม้ว่า SQL นี้จะถูกปกคลุมด้วยเลเยอร์ของ XML แต่ก็เป็น SQL มาตรฐานดังนี้
<sql> ลบจาก pl_pagewidget <ถ้า test = "widgetCodes! = null"> โดยที่ pagewidGetCode ใน <foreach collection = "widgetCodes" item = "item" index = "index" open = "(" separator = "," close = ")"> index = "index1" open = "(" separator = "," close = ")"> #{b} </foreach> </foreach> </ถ้า> <ถ้า test = "a! = null"> และ a = #{a} </if> </sql>อย่างไรก็ตามการแยกวิเคราะห์ XML ข้างต้นนั้นแตกต่างจากปกติของเรา XML นี้เป็นส่วนผสมของแท็กและข้อความ โดยปกติเราไม่ค่อยใช้การแยกวิเคราะห์ XML นี้ในการพัฒนา อย่างไรก็ตามเครื่องมือที่ใช้กันทั่วไปสำหรับการแยกวิเคราะห์ XML DOM4J สามารถแยกวิเคราะห์ SQL แบบนี้ได้เป็นอย่างดี แต่ไม่ค่อยได้ใช้ วิธีการเนื้อหา () ของคลาสองค์ประกอบสามารถส่งคืนคอลเลกชันของโหนดจากนั้นสำรวจคอลเลกชันนี้และตัดสินประเภทของแต่ละโหนด หลังจากแก้ไขประเด็นสำคัญทั้งสองนี้คุณจะต้องเพิ่มเคล็ดลับเล็กน้อยในการแยกวิเคราะห์ SQL แบบไดนามิกนี้
เคล็ดลับที่ฉันใช้ได้รับแรงบันดาลใจจากรูปแบบไวยากรณ์ Java ตัวอย่างเช่นมีตัวแปรท้องถิ่นและตัวแปรทั่วโลกใน Java และสถานการณ์ของการผ่านการอ้างอิงไม่ได้รับการพิจารณา ถ้าตัวแปรส่วนกลาง int i = 1; ตัวแปรส่วนกลางจะถูกส่งผ่านไปยังวิธีการแล้วแก้ไขในวิธีการ สิ่งที่คุณเห็นในวิธีนี้คือค่าที่เปลี่ยนแปลง แต่สิ่งที่คุณเห็นนอกวิธีนี้ยังคงเป็น 1 ในความเป็นจริงคุณควรรู้ปรากฏการณ์นี้หลังจากเรียนรู้ Java นอกจากนี้เมื่อมีการเรียกวิธีการคุณสามารถเห็นตัวแปรส่วนกลางและตัวแปรท้องถิ่นในวิธีการ หลังจากการโทรวิธีการเสร็จสิ้นตัวแปรท้องถิ่นจะถูกล้างและปล่อยออกมา (โปรดมีความสุขที่ได้เห็นนักสะสมขยะ) ฉันได้แนะนำสิ่งเหล่านี้และเพิ่มรหัสโดยตรง
นำเข้า java.io.stringReader; นำเข้า java.text.simpledateFormat; นำเข้า java.util.arrays; นำเข้า java.util.date นำเข้า java.util.hashmap; นำเข้า java.util.list; นำเข้า Java.util.map import java.util.utile org.apache.commons.collections.maputils; นำเข้า org.apache.commons.lang.stringutils; นำเข้า org.dom4j.document; นำเข้า org.dom4j.element; นำเข้า org.dom4j.node; นำเข้า org.dom4j.text; com.rd.sql.basenode; นำเข้า com.rd.sql.nodefactory; คลาสสาธารณะ sqlparser {แผนที่ส่วนตัว <String, Object> currparams = new HashMap <String, Object> (); /** ลบออกจาก pl_pagewidget <ถ้า test = "widgetCodes! = null"> โดยที่ pagewidGetCode ใน <foreach collection = "widgetCodes" item = "item" index = "index" oped = "(" separator = "," close = ")"> <ถ้าทดสอบ = "ดัชนี == 0" open = "(" separator = "," close = ")"> #{b} </foreach> </foreach> </ถ้า> <ถ้า test = "a! = null"> และ a = #{a} </if> */public Static Main (String [] args) map.put ("widgetcodes", array.aslist ("1", "2")); map.put ("bs", array.aslist ("3", "4")); map.put ("a", 1); SQLPARSER PARSER = ใหม่ SQLPARSER (); System.out .println (parser.parser ("ลบจาก pl_pageWidget/n" + "/t <ถ้าทดสอบ =/" widgetCodes! = null/">/n" + "/t/twhere pagewidGetCode ใน/n" + "/t/t < ตัวคั่น =/",/" close =/")/">/n " +"/t/t <ถ้าทดสอบ =/"ดัชนี == 0/">/n " +"/t/t #{item}/n " +"/t/t </if>/n " +"/t/t <foreach collection =/"bs/" รายการ ปิด =/")/">/n " +"/t/t/t #{b}/n " +"/t/t </foreach>/n " +"/t/t </foreach>/n " +"/t </if>/n " +"/t <ถ้าทดสอบ =/"a! = null/">/n " แผนที่)); System.out.println (parser.getParams ()); } public String parser (String XML, MAP <String, Object> Params) พ่นข้อยกเว้น {// xml = "<? xml version =/" 1.0/"encoding =/" utf-8/"?>"+xml; // ตั้งค่าเลเยอร์ของแท็ก XML สำหรับอินพุต Dynamic SQL XML = "<SQL>"+XML+"</SQL>"; saxReader reader = new SaxReader (เท็จ); Document Document = reader.read (stringreader ใหม่ (XML)); องค์ประกอบองค์ประกอบ = document.getRootelement (); แผนที่ <สตริงวัตถุ> currparams = new hashmap <string, object> (); StringBuilder sb = new StringBuilder (); // เริ่มการแยกวิเคราะห์ (องค์ประกอบ, currparams, params, sb); ส่งคืน sb.toString (); } /** * ใช้ตัวแยกวิเคราะห์แบบเรียกซ้ำเพื่อแยกวิเคราะห์ SQL แบบไดนามิก * @param Ele1 xml แท็กเพื่อแยกวิเคราะห์ * @param currparams * @param globalparams * @param sb * @throws exception * /parserelement ส่วนตัว ตัวอย่างเช่นการแยกโหนดให้แยกวิเคราะห์ถ้าการทดสอบกำหนดจริงมันจะส่งคืนจริง tempval val = parseronelement (Currparams, GlobalParams, Ele1, SB); // วัตถุโหนดนามธรรมของโหนดที่แยกวิเคราะห์โหนด basenode = val.getNode (); /*** ในความเป็นจริงคำสั่งด้านบนประโยคนี้จะแยกวิเคราะห์แท็ก XML เท่านั้นและไม่แยกวิเคราะห์เนื้อหาในแท็ก ที่นี่ * หมายความว่าก่อนที่จะแยกวิเคราะห์เนื้อหาหากมีการดำเนินการก่อนการดำเนินการก่อนการดำเนินการ */ node.pre (currparams, GlobalParams, Ele1, SB); // ปกป้องว่าเนื้อหาในโหนดยังคงต้องแยกวิเคราะห์หรือไม่ตัวอย่างเช่นหากผลการทดสอบเป็นธงบูลีนจริง = val.iscontinue (); // รับคอลเลกชันของโหนดเด็กทั้งหมดภายใต้โหนดนี้รวมถึงรายการข้อความปกติ <node> nodes = ele1.content (); if (Flag &&! nodes.isempty ()) { /*** ซึ่งหมายความว่าคุณต้องการแยกวิเคราะห์เนื้อหาในโหนดเพิ่มเติม คุณสามารถเปรียบเทียบโหนดลงในเชลล์ของวิธีการ* เนื้อหาในด้านในนั้นคล้ายคลึงกับคำสั่งเฉพาะในวิธีการ ก่อนที่จะเริ่มแยกวิเคราะห์เนื้อหาของโหนด* สร้างคอนเทนเนอร์ที่มีพารามิเตอร์โลคัลภายใต้โหนดนี้ สิ่งที่สะดวกที่สุดคือแผนที่แน่นอน */ Map <String, Object> params = new hashmap <string, object> (); /*** ใส่พารามิเตอร์ท้องถิ่นที่ส่งผ่านไปข้างนอกโดยตรงลงในคอนเทนเนอร์เนื่องจากพารามิเตอร์ในตัวอย่างนี้เป็นประเภทข้อมูลทั่วไป* จะไม่มีประเภทการอ้างอิงดังนั้นนี่จึงเทียบเท่ากับสำเนา เพื่อไม่ให้ส่งผลกระทบต่อวัตถุที่ส่งผ่านออกไปข้างนอก*คุณสามารถเปรียบเทียบกรณีที่วิธีการเรียกพารามิเตอร์ที่เข้ามา*/ params.putall (currparams); // ลูปโหนดลูกทั้งหมดสำหรับ (int i = 0; i <nodes.size ();) {node n = nodes.get (i); // ถ้าโหนดเป็นข้อความปกติถ้า (n อินสแตนซ์ของข้อความ) {สตริงข้อความ = ((ข้อความ) n) .getStringValue (); if (stringUtils.isnotEmpty (text.trim ())) {// ฝึกอบรมข้อความเช่นการประมวลผล #{xx} แทนที่ $ {yy} โดยตรงด้วยค่าจริงที่ส่งผ่านใน sb.append (handtext (ข้อความ, params, globalparams)); } i ++; } อื่นถ้า (n อินสแตนซ์ขององค์ประกอบ) {องค์ประกอบ e1 = (องค์ประกอบ) n; // การแยกวิเคราะห์องค์ประกอบเด็ก XML แบบซ้ำได้การแยกวิเคราะห์ (E1, Params, GlobalParams, SB); // หากธงลูปไม่เป็นความจริงให้แยกวิเคราะห์แท็กถัดไป // ซึ่งหมายความว่าคุณจำเป็นต้องแยกวิเคราะห์แท็กลูปซ้ำ ๆ ฉันจะไม่เปลี่ยนแปลงอีกครั้งมิฉะนั้นจะดำเนินการต่อไปบูลีนองค์ประกอบถัดไปในขณะที่ _flag = maputils.getBoolean if (! ขณะที่ _flag ||! nodefactory.ishial (n.getName ()) || e1.attributeValue (attrs.index) == null ||! e1.attributeValue (attrs.index) .equals (params.get }}} // ฉันควรทำอย่างไรหลังจากการประมวลผลโหนดโหนดหลังจาก (Currparams, GlobalParams, Ele1, SB); // รีไซเคิลพารามิเตอร์ขอบเขตปัจจุบันพารามิเตอร์ clear (); params = null; }} /** * ประมวลผลข้อความเพื่อแทนที่พารามิเตอร์ #{item} * @param str * @param params * @return * @throws Exception * /handtext สตริงส่วนตัว (สตริง str, แผนที่ <สตริง, วัตถุ> พารามิเตอร์, แผนที่ <สตริง, วัตถุ> globalparams) ดัชนีจำนวนเต็ม = null; if (stringutils.isnotEmpty (indexstr)) {index = maputils.getInteger (params, indexstr); } // จับคู่ #{a} พารามิเตอร์สตริง reg1 = "( #// {) (// w+) (//})"; // จับคู่พารามิเตอร์ของ $ {a} string reg2 = "(// $ // {) (// w+) (//})"; รูปแบบ p1 = pattern.compile (reg1); matcher m1 = p1.matcher (str); รูปแบบ p2 = pattern.compile (reg2); matcher m2 = p2.matcher (str); String ในขณะที่ = maputils.getString (params, attrs.harial_list); แผนที่ <สตริงวัตถุ> allParams = getAllParams (params, globalparams); ในขณะที่ (m1.find ()) {string tmpkey = m1.group (2); String key = ในขณะที่ == null? tmpkey: (ในขณะที่+"_"+tmpkey); key = index == null? key: (key+index); string rekey = "#{"+คีย์+"}"; // ถ้าอยู่ในลูปที่คล้ายกับ foreach คุณอาจต้องแทนที่พารามิเตอร์ #{xx} ด้วย #{xx_0}, #{xx_1} str = str.replace (m1.group (0), rekey); currparams.put (คีย์, allparams.get (tmpkey)); } ในขณะที่ (m2.find ()) {string tmpkey = m2.group (2); ค่าวัตถุ = AllParams.get (tmpkey); if (value! = null) {str = str.replace (m2.group (0), getValue (ค่า)); }} return str; } สตริงส่วนตัว getValue (ค่าวัตถุ) {string result = ""; if (ค่าอินสแตนซ์ของค่า) {simpledateFormat sdf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); result = sdf.format ((วันที่) ค่า); } else {result = string.valueof (ค่า); } ผลตอบแทนผลลัพธ์; } แผนที่ส่วนตัว <String, Object> GetAllParams (แผนที่ <String, Object> Currparams, Map <String, Object> GlobalParams) {Map <String, Object> AllParams = ใหม่ HashMap <String, Object> (); AllParams.putall (GlobalParams); AllParams.putall (currparams); คืน Allparams; } // แยกวิเคราะห์องค์ประกอบ XML ส่วนตัว tempval parseroneElement (แผนที่ <สตริงวัตถุ> currparams, แผนที่ <สตริง, วัตถุ> globalparams, element ele, stringbuilder sb) โยนข้อยกเว้น {// รับชื่อแท็ก XML // มันดำเนินต่อไปหลังจากแยกโหนดหรือไม่? หากคุณพบโหนดเช่นถ้าคุณต้องพิจารณาว่าการทดสอบนั้นว่างเปล่าหรือไม่ บูลีน iscontinue = false; // ประกาศโหนดโหนดนามธรรมโหนด = null; if (stringUtils.isnotEmpty (elename)) {// ใช้โรงงานโหนดเพื่อรับวัตถุโหนดตามชื่อโหนดเช่นถ้าโหนดหรือ foreach โหนดโหนด = nodeFactory.create (elename); // วิเคราะห์โหนดนี้และส่งคืนว่าเนื้อหาในโหนดยังคงต้องถูกแยกวิเคราะห์ iscontinue = node.parse (currparams, GlobalParams, Ele, SB); } ส่งคืน tempval ใหม่ (Iscontinue, ele, โหนด); } แผนที่สาธารณะ <String, Object> getParams () {return currparams; } / *** ห่อหุ้มผลลัพธ์หลังจากองค์ประกอบ XML ถูกแยกวิเคราะห์* @author rongdi* / คลาสคงที่คลาสคงที่ tempval {บูลีนส่วนตัว iscontinue; องค์ประกอบส่วนตัว ele; โหนด basenode ส่วนตัว; Public Tempval (Boolean Iscontinue, Element Ele, โหนด basenode) {this.iscontinue = iScontinue; this.ele = ele; this.node = node; } บูลีนสาธารณะ iScontinue () {return iscontinue; } โมฆะสาธารณะ setContinue (บูลีน iScontinue) {this.iscontinue = iScontinue; } องค์ประกอบสาธารณะ getele () {return ele; } โมฆะสาธารณะ setele (องค์ประกอบ ele) {this.ele = ele; } สาธารณะ basenode getNode () {return node; } โมฆะสาธารณะ setNode (โหนด basenode) {this.node = node; - นำเข้า org.dom4j.element; นำเข้า java.util.hashmap; นำเข้า java.util.map;/*** บทคัดย่อโหนด* @author rongdi*/บทคัดย่อคลาสสาธารณะ basenode {บทคัดย่อสาธารณะ parse (แผนที่ <String, Object> Curnerms โมฆะสาธารณะก่อน (แผนที่ <สตริงวัตถุ> currparams, แผนที่ <สตริง, วัตถุ> globalparams, องค์ประกอบ ele, stringbuilder sb) โยนข้อยกเว้น {} โมฆะสาธารณะหลังจาก (แผนที่ <สตริง, วัตถุ> currparams, แผนที่ <สตริง, วัตถุ> globalparams, องค์ประกอบ ele, stringbuilder sb) แผนที่ <string, Object> GlobalParams) {Map <String, Object> AllParams = new HashMap <String, Object> (); AllParams.putall (GlobalParams); AllParams.putall (currparams); คืน Allparams; - นำเข้า java.util.map; นำเข้า ognl.ognl; นำเข้า org.apache.commons.lang.stringutils; นำเข้า org.dom4j.element;/*** ถ้า node* @author rongdi*/คลาสสาธารณะ ifnode ขยาย basenode ELE, StringBuilder SB) โยนข้อยกเว้น {// รับแอตทริบิวต์การทดสอบของ IF Node String testStr = Ele.attributeValue ("Test"); การทดสอบบูลีน = false; ลอง {ถ้า (stringutils.isnotEmpty (testStr)) {// ผสานตัวแปรทั่วโลกและตัวแปรโลคัลแผนที่ <สตริง, วัตถุ> allParams = getAllParams (currparams, globalparams); // ใช้ OGNL เพื่อตรวจสอบการทดสอบจริงหรือเท็จ = (บูลีน) ognl.getValue (TestStr, AllParams); }} catch (exception e) {e.printstacktrace (); โยนข้อยกเว้นใหม่ ("พารามิเตอร์การดำเนินการตัดสิน"+testStr+"ผิดกฎหมาย"); } if (ele.content ()! = null && ele.content (). size () == 0) {test = true; } การทดสอบส่งคืน; - นำเข้า java.util.arraylist; นำเข้า java.util.hashmap; นำเข้า java.util.list; นำเข้า java.util.map นำเข้า java.util.set; นำเข้า ognl.ognl; นำเข้า org.apache.commons.collections.maputils; org.dom4j.element;/** แอตทริบิวต์ของโหนด foreach มีดังนี้รายการรวบรวมที่ต้องผ่าน ดัชนีตัวแปรที่เก็บไว้ในแต่ละองค์ประกอบหลังจากข้ามการรวบรวม หมายเลขดัชนีของคอลเลกชันเป็นเช่น 0, 1, 2 ... ตัวคั่นหลังจากผ่านการสำรวจการประกบเปิดด้วยตัวคั่นที่ระบุ สัญลักษณ์ที่เริ่มการประกบหลังการสำรวจมีดังนี้ (ปิดสัญลักษณ์ที่สิ้นสุดการประกบหลังจากการเดินทางผ่านมีดังนี้) */คลาสสาธารณะ foreachNode ขยาย basenode {@Override บูลีนสาธารณะแยกวิเคราะห์ (MAP <String, Object> currparams, แผนที่ String CollectionSTR = Ele.attributeValue ("คอลเลกชัน"); string itemtr = ele.attributeValue ("item"); string index = ele.attributeValue ("index"); String separatorstr = ele.attributeValue ("ตัวคั่น"); สตริง openstr = ele.attributeValue ("เปิด"); String closeStR = ele.attributeValue ("ปิด"); if (stringUtils.isEmpty (ดัชนี)) {index = "index"; } if (stringUtils.isEmpty (ตัวแยก)) {ตัวแยก = ","; } if (stringUtils.isnotEmpty (openstr)) {currparams.put (attrs.harent_open, openstr); } if (stringUtils.isnotEmpty (ใกล้ชิด)) {currparams.put (attrs.harent_close, ใกล้ชิด); } if (stringUtils.isnotEmpty (CollectionStr)) {currparams.put (attrs.harent_list, collectionStr); } currparams.put (attrs.harht_separator, separatorstr); ถ้า (ดัชนี! = null) { /*** หากมีค่าของตัวแปรลูปปัจจุบันในตัวแปรโลคัลหมายความว่าไม่ใช่ครั้งแรกที่คุณป้อนป้ายลูป ลบแท็กเริ่มต้น * และเพิ่ม 1 ในค่าตัวแปรท้องถิ่น */ if (currparams.get (ดัชนี)! = null) {currparams.remove (attrs.harent_start); currparams.put (ดัชนี+"_", (จำนวนเต็ม) currparams.get (ดัชนี+"_")+1); } else {// ครั้งแรกที่คุณป้อน Loop Label Currparams.put (attrs.harial_start, true); currparams.put (ดัชนี+"_", 0); } currparams.put (ดัชนี, (จำนวนเต็ม) currparams.get (ดัชนี+"_")); } เงื่อนไขบูลีน = true; แผนที่ <สตริงวัตถุ> allParams = getAllParams (currparams, globalparams); การรวบรวมวัตถุ = null; if (stringUtils.isnotEmpty (คอลเลกชัน str)) {// รับคอลเลกชันที่จะวนลูปคอลเลกชัน = ognl.getValue (CollectionSTR, AllParams); // หากคุณสมบัติการรวบรวมไม่ว่างเปล่า แต่เงื่อนไขเป็นโมฆะเงื่อนไขขอบเขตจะถูกเพิ่มโดยค่าเริ่มต้นถ้า (stringutils.isempty (conditionstr)) {// ที่นี่ฉันจะใช้คอลเลกชันเพื่อสาธิต นอกจากนี้คุณยังสามารถเพิ่มอาร์เรย์ได้ แต่เพียงเปลี่ยนเป็น. length ถ้า (รายการอินสแตนซ์คอลเลกชัน) {conditionstr = index+"_ <"+collectionStr+". size ()"; } อื่นถ้า (การรวบรวมอินสแตนซ์ของแผนที่) {map map = (แผนที่) คอลเลกชัน; set set = map.entryset (); list list = new ArrayList (set); AllParams.put ("_ list_", รายการ); conditionstr = index+"_ <_ list _"+". size ()"; }}} currparams.remove (attrs.harial_end); if (stringutils.isnotEmpty (เงื่อนไข)) {// ค่าของเงื่อนไขการคำนวณสภาพเงื่อนไข = (บูลีน) ognl.getValue (conditionstr, allParams); แผนที่ <string, Object> tempMap = ใหม่ hashmap <> (); tempmap.putall (allparams); tempmap.put (ดัชนี+"_", (จำนวนเต็ม) currparams.get (ดัชนี+"_")+1); currparams.put (attrs.harial_end,! (บูลีน) ognl.getValue (conditionstr, tempmap)); } ธงบูลีน = true; currparams.put (attrs.havial_index, index); currparams.put (attrs.havial_flag, true); if (เงื่อนไข) {ลอง {ถ้า (stringUtils.isnotEmpty (itemstr) && stringutils.isnotEmpty (คอลเลกชัน striced)) {ค่าวัตถุ = null; int idx = integer.parseint (currparams.get (ดัชนี+"_"). toString ()); if (รายการอินสแตนซ์ของการรวบรวม) {value = ((รายการ) การรวบรวม) .get (idx); currparams.put (itemstr, value); } อื่นถ้า (การรวบรวมอินสแตนซ์ของแผนที่) {map map = (แผนที่) คอลเลกชัน; set <map.entry <string, object >> set = map.entryset (); รายการ <map.entry <string, object >> list = new ArrayList (set); currparams.put (itemstr, list.get (idx) .getValue ()); currparams.put (index, list.get (idx) .getKey ()); }}} catch (exception e) {โยนข้อยกเว้นใหม่ ("รับค่าจากคอลเลกชันหรือแผนที่"+currparams.get (ดัชนี)+"ข้อผิดพลาด"+e.getMessage ()); }} else {flag = false; DestroyVars (Currparams, INDEX, ItemSTR); } return flag; } / *** หากเป็นครั้งแรกที่คุณป้อนแท็กลูปสะกดเนื้อหาของช่องเปิด* / @Override โมฆะสาธารณะก่อน (แผนที่ <สตริงวัตถุ> currparams, แผนที่ <สตริง, วัตถุ> GlobalParams, Element Ele, StringBuilder SB) บูลีนเริ่มต้น = maputils.getBoolean (currparams, attrs.hial_start, false); if (start) {string open = maputils.getString (currparams, attrs.harial_open); sb.append (เปิด); }} / *** หากมีการป้อนฉลากลูปในที่สุดเนื้อหาของปิดจะถูกสะกดในท้ายที่สุด* / @Override โมฆะสาธารณะหลังจาก (แผนที่ <สตริง, วัตถุ> currparams, แผนที่ <สตริง, วัตถุ> GlobalParams, Element Ele, StringBuilder SB) บูลีน End = maputils.getBoolean (currparams, attrs.harial_end, false); String separator = maputils.getString (currparams, attrs.harial_separator); if (! end && stringutils.isnotEmpty (ตัวคั่น)) {sb.append (ตัวคั่น); } if (end) {String Close = mapUtils.getString (currparams, attrs.harial_close); if (sb.toString (). endswith (ตัวคั่น)) {sb.deletecharat (sb.length () - 1); } sb.append (ปิด); }} // ปล่อยโมฆะส่วนตัวตัวแปรชั่วคราว destroyVars (แผนที่ <สตริงวัตถุ> currparams, ดัชนีสตริง, สตริง varstr) {currparams.remove (attrs.harile_index); currparams.remove (attrs.havial_flag); currparams.remove (attrs.harial_separator); currparams.remove (attrs.harial_start); currparams.remove (attrs.harial_end); currparams.remove (attrs.havial_list); }} นำเข้า org.dom4j.element; นำเข้า java.util.map; คลาสสาธารณะ sqlnode ขยาย basenode {@Override บูลีนสาธารณะแยกวิเคราะห์ (แผนที่ <สตริง, วัตถุ> currparams, แผนที่ <สตริง, วัตถุ> globalparams, องค์ประกอบ ele, stringbuilder sb) }} นำเข้า java.util.Arrays; นำเข้า java.util.list; นำเข้า java.util.map; นำเข้า java.util.concurrent.concurrenthashmap;/*** Node Factory*/คลาสสาธารณะ รายการคงที่ส่วนตัวสุดท้าย <String> ในขณะที่ array.aslist ("foreach"); คงที่ {nodemap.put ("ถ้า", ifnode ใหม่ ()); nodemap.put ("SQL", sqlnode ใหม่ ()); nodemap.put ("foreach", foreachNode ใหม่ ()); } บูลีนคงที่สาธารณะคือในขณะที่ (String ElementName) {return ในขณะที่ contains.contains (ElementName); } โมฆะคงที่สาธารณะ addNode (String nodeName, โหนด basenode) {nodemap.put (nodeName, โหนด); } basenode คงที่สาธารณะสร้าง (string nodename) {return nodemap.get (nodeName); }}/*** แท็กต่าง ๆ* @author rongdi*/คลาสสาธารณะ attrs {public final String transactional = "transactional"; สตริงคงที่สาธารณะสุดท้ายในขณะที่ _start = "ในขณะที่เริ่มต้น"; สตริงคงที่สาธารณะสุดท้ายในขณะที่ _END = "ในขณะที่ end"; สตริงคงที่สาธารณะสุดท้ายในขณะที่ _open = "ขณะเปิด"; สตริงคงที่สาธารณะสุดท้ายในขณะที่ _close = "ในขณะที่อยู่ใกล้"; สตริงคงที่สาธารณะสุดท้ายในขณะที่ _Separator = "ในขณะที่แยก"; สตริงคงที่สาธารณะสุดท้ายในขณะที่ _index = "ในขณะที่ดัชนี"; สตริงคงที่สาธารณะสุดท้ายในขณะที่ _flag = "ในขณะที่ flag"; สตริงคงที่สาธารณะสุดท้ายในขณะที่ _list = "ในขณะที่รายการ"; สตริงคงที่สาธารณะสุดท้ายเมื่อ _flag = "เมื่อ flag"; สตริงสุดท้ายคงที่ process_var = "process-var"; สตริงคงที่สุดท้ายของสาธารณะผลลัพธ์ _flag = "result-flag"; สตริงคงสุดท้ายสาธารณะ return_flag = "return-flag"; สาธารณะสุดท้ายสตริงคงที่ console_var = "console-var"; สตริงคงที่สาธารณะสุดท้าย DO = "DO"; ดัชนีสตริงคงสุดท้ายสาธารณะสุดท้าย = "ดัชนี"; สภาพสตริงคงสุดท้ายสุดท้ายสาธารณะ = "เงื่อนไข"; ชื่อสตริงคงที่สาธารณะสุดท้าย = "ชื่อ"; ค่าสตริงคงสุดท้ายสุดท้ายของสาธารณะ = "ค่า"; สตริงสุดท้ายคงที่สาธารณะประเภท = "ประเภท"; รูปแบบสตริงสุดท้ายคงที่สาธารณะ = "รูปแบบ"; สตริงสุดท้ายคงที่สาธารณะถ้า = "ถ้า"; สตริงสุดท้ายคงที่สาธารณะอื่น = "อื่น"; ไฟล์สตริงคงสุดท้ายสุดท้ายสาธารณะ = "ไฟล์"; วันที่สตริงสุดท้ายคงที่ = "วันที่"; สตริงสุดท้ายคงที่สาธารณะตอนนี้ = "ตอนนี้"; สาธารณะคงที่สาธารณะสุดท้ายสตริงทศนิยม = "ทศนิยม"; สตริงสุดท้ายคงที่สาธารณะ ID = "id"; พารามิเตอร์สตริงสุดท้ายคงที่สาธารณะ = "params"; เป้าหมายสตริงสุดท้ายคงที่สาธารณะ = "เป้าหมาย"; สตริงสุดท้ายคงที่ single = "single"; public String String Paging สุดท้าย = "Paging"; สตริงสุดท้ายคงที่สาธารณะ desc = "desc"; String Final Final Final Break = "Break"; สตริงสุดท้ายคงที่สาธารณะดำเนินการต่อ = "ดำเนินการต่อ"; การสะสมสตริงสุดท้ายคงที่สาธารณะ = "คอลเลกชัน"; สตริงสุดท้ายคงที่สาธารณะ var = "var"; String String สุดท้ายสาธารณะคงที่ executor = "Executor-1"; สาธารณะคงที่สตริงสุดท้าย RollBack_flag = "Rollback-flag"; บริการสตริงสุดท้ายคงที่สาธารณะ = "บริการ"; สตริงสุดท้ายคงที่สาธารณะ ref = "ref"; สตริงสุดท้ายคงที่สาธารณะ bizs = "bizs"; Public Static Final String Titles = "ชื่อ"; คอลัมน์สตริงสุดท้ายคงที่สาธารณะ = "คอลัมน์"; สาธารณะคงที่สตริงสุดท้าย curruser = "curruser"; สตริงสุดท้ายคงที่ currperm = "currperm"; String สุดท้ายคงที่สาธารณะ task_executor = "taskexecutor"; ตัวคั่นสตริงสุดท้ายคงที่สาธารณะ = "ตัวคั่น"; สตริงสุดท้ายคงที่สาธารณะ operName = "operName"; } currparams.remove (varstr); currparams.remove (ดัชนี); currparams.remove (ดัชนี+"_"); -แนบไฟล์ POM
<Project xmlns = "http://maven.apache.org/pom/4.0.0" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" xsi: schemalocation = "http:/MANCMMMMMMMMMMMMMMMMMMMMMMMMMMBM http://maven.apache.org/maven-v4_0_0.xsd "> <moderVersion> 4.0.0 </modelversion> <roupid> com.rd </groupId> <ArtIfactId> Parser </artifactid> <url> http://maven.apache.org </url> <การพึ่งพา> <การพึ่งพา> <roupId> dom4j </groupId> <ratifactid> dom4j </artifactid> <cersion> 1.6.1 </เวอร์ชัน> <Sersion> 2.6.11 </Senture> </derctency> <การพึ่งพา> <roupId> คอมมอนส์-คอลเลคชั่น </groupID> <ArtIfactId> Commons-collections </artifactid> <version> 3.2.1 </เวอร์ชัน> </การพึ่งพา> <Ederency> <sdeperency> junit </groupId> <ratifactid> Junit </artifactid> <version> 3.8.1 </เวอร์ชัน> <cope> ทดสอบ </cope> </predency> </การพึ่งพา> </การพึ่งพาอาศัย> <ufflet> <resources> </cold> </resource> <resource> <ไดเรกทอรี> SRC/Main/Resources </Directory> <cencal> <รวมถึง **/*</รวมถึง> </sursece> </sursesore> </testResources> <TestResources> <TestResource> <Sirectory> $ {project.basedir}/src/test/resources </directory> </testresource> </sestresources> <plugins> <slouprid> org.apache.maven.plugins </groupid> <source> 1.8 </secoding> <coding> UTF-8 </Scoding> </การกำหนดค่า> </plugin> </plugins> </ufferวิธีการข้างต้นในการใช้ MyBatis Dynamic SQL ด้วยตัวเองคือเนื้อหาทั้งหมดที่ฉันได้แบ่งปันกับคุณ ฉันหวังว่าคุณจะให้ข้อมูลอ้างอิงและฉันหวังว่าคุณจะสนับสนุน wulin.com มากขึ้น