Saya menemukan bahwa sangat sulit untuk bersikeras menulis blog, dan berbagai alasan tidak perlu menjaga blog. Saya awalnya berencana untuk menulis implementasi ORM DIY dan melihat waktu. Saya lebih suka menerapkan SQL dinamis terlebih dahulu dan menambahkan implementasi ORM yang lengkap lain kali saya punya waktu.
Orang -orang yang menggunakan mybatis mungkin akrab dengan SQL dinamis. Jika Anda belum menggunakannya, lihatlah kesenangannya. Pertama kali saya melakukan kontak dengan MySQL adalah ketika saya berada di tahun senior saya. Pada saat itu, saya pikir Dynamic SQL sangat luar biasa dan fleksibel. Saya selalu ingin mencari cara menerapkannya. Meskipun saya bisa menulis kerangka kerja IOC, MVC, dan ORM sederhana pada waktu itu (meniru mybaits tetapi tidak ada bagian SQL yang dinamis), saya masih tidak dapat menemukan di mana harus mengimplementasikan SQL dinamis di inti mybatis dan bagaimana mengimplementasikannya. Mungkin kodenya terlalu kusut dan saya tidak bisa memahaminya sama sekali. Sampai sekarang, saya tidak memiliki keberanian untuk membaca bagian SQL yang dinamis dari mybatis. Mungkin saya dilahirkan dengan kekaguman yang tidak bisa dijelaskan terhadap algoritma.
Beberapa tahun yang lalu, karena saya ingin membangun platform konfigurasi dan ingin menggunakan bahasa parsing untuk menggantikan implementasi Java, yang memungkinkan personel konfigurasi untuk dengan mudah menulis sejumlah kecil kode pada halaman untuk menerapkan logika bisnis yang kompleks (termasuk operasi basis data). Pada saat itu, Java sudah memiliki mesin parsing JS, tetapi kebanyakan orang mengatakan bahwa efisiensinya terlalu rendah. Jika saya tidak tahu apa yang saya tergila -gila, saya berpikir untuk menerapkan bahasa parsing sendiri. Namun, saya selalu bermimpi mewujudkan bahasa saya sendiri. Lebih mudah untuk memulai dengan bahasa analitik daripada bahasa yang dikompilasi, jadi saya mulai melakukannya dengan tegas. Setelah menulisnya, saya menyadari bahwa implementasi saya mungkin tidak seefisien mesin JS pada waktu itu. Pada saat itu, saya benar -benar muda dan sederhana. Implementasi SQL dinamis yang saya bicarakan hari ini sebenarnya terinspirasi oleh bahasa penguraian pada waktu itu.
Mari kita bicara tentang SQL dinamis tanpa mengatakan omong kosong. Silakan lihat contoh berikut. Pertama, saya menyatakan bahwa contoh di sini bukan cara yang benar untuk menulis SQL. Saya hanya ingin menulis struktur bersarang yang serumit mungkin. Jika situasi yang kompleks ini diimplementasikan, maka bahkan lebih sulit untuk membuatnya sederhana.
Hapus dari PL_PAGEWIDGET <if test = "widgetCodes! = null"> di mana pagewidgetCode di <freeach collection = "widgetcodes" item = "item" index = "index" open = "(" pemisah = "," close = ")"> <if test = "index == 0"> #{item} </if> ") <if test =" index == 0 "> #{item} </if>" ifeach = for = "index == 0"> #{item} </if> "ifeach = for =" index == 0 "> #{item} </if>" ifeach = for = "index == 0"> #{item} </if> " open = "(" pitaor = "," close = ")"> #{b} </tandingeach> </tandingeach> </if> <if test = "a! = null"> dan a = #{a} </if>Untuk mengimplementasikan SQL untuk mem -parsing contoh di atas, salah satu kesulitannya mirip dengan bagaimana menentukan kondisi benar atau salah dalam atribut pengujian. Namun, kesulitan ini lebih di depan ekspresi OGNL yang dipelajari di Struts2. Saya tidak tahu apakah seorang teman telah menemukan fenomena yang agak aneh, yaitu, kadang -kadang ekspresi berikut ditulis dalam mybatis dinamis SQL, tetapi ketika n = 0, itu sebenarnya memenuhi kondisi, yaitu, nilai tes salah, dan 0 tidak dapat memenuhi kondisi ekspresi ini. Inilah alasan perpustakaan OGNL. Tidak mungkin itu hanya bermain seperti ini, ingat saja sebagai situasi khusus
test = "n! = null dan n! = ''"
Ekspresi OGNL sangat nyaman untuk digunakan sebagai berikut
impor java.util.hashmap; import java.util.map; import ognl.ognl; kelas publik ognltest {// hasil output: false public static main (string [] args) melempar pengecualian {string con1 = "n! = null dan n! = '" "; Peta <string, object> root = new HashMap <> (); root.put ("n", 0); System.out.println (ognl.getValue (con1, root)); }}Untuk mengimplementasikan SQL untuk parsing contoh di atas, kesulitan kedua adalah bahwa meskipun SQL ini ditutupi dengan lapisan XML, itu adalah SQL standar, sebagai berikut
<sql> hapus dari pl_pagewidget <if test = "widgetCodes! = null"> di mana pageWidgetCode dalam <foreach collection = "widgetcodes" item = "item" index = "index" open = "(" PARATOR = "," close = ") <if test =" index == 0 "> #" item {"foreach =} <foreach = if test =" index == 0 "> #" " index = "index1" open = "(" pemisah = "," close = ")"> #{b} </tandingeach> </tandingeach> </if> <if test = "a! = null"> dan a = #{a} </if> </sql>Namun, parsing XML di atas berbeda dari yang biasa kami lakukan. XML ini adalah campuran tag dan teks. Biasanya, kita jarang menggunakan parsing XML ini dalam pengembangan. Namun, alat yang umum digunakan untuk parsing XML DOM4J sebenarnya dapat mengurai SQL semacam ini dengan sangat baik, tetapi jarang digunakan. Metode konten () dari kelas elemen dapat mengembalikan kumpulan node, dan kemudian melintasi koleksi ini dan menilai jenis masing -masing node. Setelah menyelesaikan dua poin utama ini, Anda hanya perlu menambahkan sedikit trik untuk mengurai SQL dinamis ini.
Trik yang saya gunakan terinspirasi oleh format sintaks Java. Misalnya, ada variabel lokal dan variabel global di Java, dan situasi lewat referensi tidak dipertimbangkan. Jika variabel global int i = 1; Variabel global diteruskan ke dalam metode dan kemudian dimodifikasi dalam metode ini. Apa yang Anda lihat dalam metode ini adalah nilai yang diubah, tetapi apa yang Anda lihat di luar metode ini masih 1. Bahkan, Anda harus mengetahui fenomena ini setelah belajar Java. Juga, ketika metode ini dipanggil, Anda dapat melihat variabel global dan variabel lokal dalam metode ini. Setelah panggilan metode selesai, variabel lokal akan dihapus dan dirilis (senang melihat pengumpul sampah). Saya telah memperkenalkan ini dan secara langsung menambahkan kode
Impor java.io.stringreader; impor java.text.simpledateFormat; impor java.util.arrays; impor java.util.date; impor java.util.hashmap; impor java.util.list; impor java.util.util.map; Import java.util.perat. org.apache.commons.collections.maputils; impor org.apache.commons.lang.stringutils; impor org.dom4j.document; impor org.dom4j.element; impor org.dom4j.node; impor org.dom.text; impor org.dom4j.node; impor org.dom.text; impor org.dom4j.oP.node; org.dom.text; impor org.dom4j.oox; com.rd.sql.basenode; import com.rd.sql.nodefactory; kelas publik sqlparser {peta privat <string, object> currparams = hashmap baru <string, object> (); /** delete from pl_pagewidget <if test="widgetcodes != null"> where pagewidgetcode in <foreach collection="widgetcodes" item="item" index="index" open="(" separator="," close=")"> <if test="index == 0"> #{item} </if> <foreach collection="bs" item="b" index="index1" open="(" separator="," close=")"> #{b} </foreach> </foreach> </if> <if test="a != null"> and a = #{a} </if> */ public static void main(String[] args) throws Exception { Map<String, Object> map = new HashMap<String, Object>(); peta.put ("widgetCodes", arrays.aslist ("1", "2")); peta.put ("BS", arrays.aslist ("3", "4")); Map.put ("A", 1); Sqlparser parser = sqlparser baru (); System.out .println (parser.parser ("hapus dari pl_pagewidget/n" + "/t <if test =/" widgetCodes! = Null/">/n" + "/t/twhere pagewidgetCode in/n" + "/t/t <foreach collection =/" widgetcodes/"" "" "" "" " pemisah =/",/" tutup =/")/">/n " +"/t/t <if test =/"index == 0/">/n " +"/t/t #{item}/n " +"/t/t </if>/n " +"/t/t <foreach collection =/"bs/" item =/"b/" "" "" tutup =/")/">/n " +"/t/t/t #{b}/n " +"/t/t </tandingeach>/n " +"/t/t </tandingeach>/n " +"/t </if>/n "/t/t <if test =/" a! = null/">/n"/t/t/t/t <if test =/"a! = null/">/n "/n"/t/t a = "{a! = null/">/n ""/t/t/t <if test =/"a! = null/">/n ""/t/t/t a = "{a! = null/">/n ""/t/t/t a = "{a! peta)); System.out.println (parser.getParams ()); } public string parser (string xml, peta <string, object> params) melempar Exception {// xml = "<? Xml Version =/" 1.0/"encoding =/" utf-8/"?>"+xml; // Atur lapisan tag XML untuk input dinamis SQL xml = "<sql>"+xml+"</sql>"; Saxreader Reader = Saxreader baru (false); Dokumen dokumen = reader.read (stringReader baru (xml)); Elemen elemen = document.getrooteLement (); Peta <String, Object> Currparams = HashMap baru <String, Object> (); StringBuilder SB = StringBuilder baru (); // Mulai ParserElement (Elemen, Currparams, Params, SB); return sb.tostring (); } /** * Use recursive parser to parse dynamic sql * @param ele1 xml tag to be parsed* @param currParams * @param globalParams * @param sb * @throws Exception */ private void parserElement(Element ele1, Map<String, Object> currParams, Map<String, Object> globalParams, StringBuilder sb) throws Exception { // Parsen sebuah node, misalnya, parse node IF, jika tes menentukan benar, itu mengembalikan true. Tempval Val = ParseroneElement (Currparams, GlobalParams, ELE1, SB); // Objek node abstrak dari simpul node basenode yang diuraikan = val.getNode (); /*** Faktanya, pernyataan di atas kalimat ini hanya menguraikan tag XML dan tidak mengurai konten dalam tag. Di sini * berarti bahwa sebelum mem-parsing konten, jika ada pra-operasi, lakukan beberapa pra-operasi */ node.pre (Currparams, GlobalParams, ELE1, SB); // Pertahankan apakah konten dalam node masih perlu diuraikan, misalnya, jika hasil tes benar bendera boolean = val.iscontinue (); // Dapatkan koleksi semua node anak di bawah node ini, termasuk daftar teks normal <node> node = ele1.content (); if (flag &&! nodes.isempty ()) { /*** Ini berarti Anda ingin lebih mem -parsing konten di node. Anda dapat membandingkan node ke dalam shell metode* Konten di dalam adalah analog dengan pernyataan spesifik dalam metode ini. Sebelum mulai mengurai konten node* Buat wadah dengan parameter lokal di bawah simpul ini. Yang paling nyaman adalah peta tentu saja */ peta <string, objek> params = hashmap baru <string, objek> (); /*** Masukkan parameter lokal yang diteruskan langsung ke luar ke dalam wadah, karena parameter dalam contoh ini adalah tipe data umum* tidak akan ada jenis referensi, jadi ini setara dengan salinan. Agar tidak mempengaruhi objek yang diteruskan di luar*, Anda dapat membandingkan kasus di mana metode memanggil parameter yang masuk*/ params.putAll (Currparams); // loop semua node anak untuk (int i = 0; i <nodes.size ();) {node n = nodes.get (i); // Jika node adalah teks normal jika (n instance dari teks) {string text = ((text) n) .getStringValue (); if (stringutils.isnotempty (text.trim ())) {// latih teks, seperti pemrosesan #{xx}, langsung ganti $ {yy} dengan nilai nyata yang diteruskan dalam sb.append (handtext (text, params, globalparams)); } i ++; } lain jika (n instanceof elemen) {elemen e1 = (elemen) n; // Parse secara rekursif elemen anak XML Parserelement (E1, Params, GlobalParams, SB); // Jika bendera loop tidak benar, parse tag berikutnya // ini berarti Anda harus berulang kali menguraikan tag loop, maka saya tidak akan berubah, jika tidak terus memproses elemen berikutnya boolean while_flag = maputils.getboolean (params, attrs.while_flag, false); if (! while_flag ||! nodefactory.ishile (n.getName ()) || e1.attributeValue (attrs.index) == null ||! e1.attributeValue (attrs.index) .Equals (params.get (attrs.while_index))) {i ++; }}} // Apa yang harus saya lakukan setelah node pemrosesan node.after (Currparams, GlobalParams, ELE1, SB); // daur ulang parameter lingkup saat ini parameter.clear (); params = null; }} /** * Proses teks untuk menggantikan parameter #{item} * @param str * @param params * @return * @throws Exception * /private string handtext (string str, peta <string, objek> params, peta <string, objek> globalparams) lemparan {// dapatkan variabel string indexstr = maputstr = maputstring. Maputstr = maputstr = maputstr = mapUrstring. Maputstr = maputstr = maputstr = maputstr = mapUrstring. Maputstr = maputstr = maputstr = maputstr = mapUrstring. Maputstr = maputstr = maputstr = maputstr = maputstring. Maputstr = maputstr = maputstr = maputstr = maputstr. Indeks Integer = NULL; if (stringutils.isNotEmpty (indexstr)) {index = maputils.getInteger (params, indexstr); } // cocok #{a} parameter string reg1 = "( #// {) (// w+) (//})"; // Cocokkan parameter $ {a} string reg2 = "(// $ // {) (// w+) (//})"; Pola p1 = pola.compile (reg1); Pencocokan m1 = p1.matcher (str); Pola p2 = pola.compile (reg2); Pencocokan m2 = p2.matcher (str); String whilelist = maputils.getString (params, attrs.while_list); Peta <String, Object> AllParams = getAllParams (params, GlobalParams); while (m1.find ()) {string tmpKey = m1.group (2); String key = whileList == null? TmpKey: (whilelist+"_"+tmpKey); key = index == NULL? KUNCI: (KEY+INDEX); String rekey = "#{"+key+"}"; // Jika dalam loop yang mirip dengan foreach, Anda mungkin perlu mengganti parameter #{xx} dengan #{xx_0}, #{xx_1} str = str.replace (m1.group (0), rekey); Currparams.put (tombol, allparams.get (tmpey)); } while (m2.find ()) {string tmpKey = m2.group (2); Nilai objek = allparams.get (tmpKey); if (value! = null) {str = str.replace (m2.group (0), getValue (value)); }} return str; } private string getValue (nilai objek) {string result = ""; if (value instanceOf date) {SimpleDateFormat SDF = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); hasil = nilai sdf.format ((tanggal)); } else {result = string.valueof (value); } hasil pengembalian; } peta pribadi <String, Object> getAllParams (peta <String, Object> Currparams, Map <String, Object> GlobalParams) {MAP <String, Object> allParams = new HashMap <String, Object> (); allparams.putall (GlobalParams); allparams.putall (Currparams); mengembalikan allparams; } // Parsen elemen xml private tempval parseroneElement (peta <string, objek> arus, peta <string, objek> globalparams, elemen ele, stringbuilder sb) melempar pengecualian {// dapatkan nama tag xml string elename = ele.getName (); // Apakah itu berlanjut setelah mem -parsing node? Jika Anda menemukan simpul seperti IF, Anda perlu menentukan apakah tesnya kosong. boolean isContinue = false; // nyatakan simpul node abstrak node = null; if (stringutils.isnotempty (elename)) {// Gunakan pabrik simpul untuk mendapatkan objek node berdasarkan nama simpul, seperti if node atau node node foreach = nodefactory.create (elename); // Analisis node ini dan kembalikan apakah konten dalam node masih perlu diuraikan iscontinue = node.parse (Currparams, GlobalParams, ELE, SB); } return Tempval baru (isContinue, ele, node); } peta publik <String, Object> getParams () {return Currparams; } / *** merangkum hasilnya setelah elemen XML diuraikan* @author rongdi* / kelas statis final tempval {private boolean isContinue; elemen pribadi ele; node basenode pribadi; Tempval publik (boolean isContinue, elemen ele, node basenode) {this.iscontinue = isContinue; this.ele = ele; this.node = node; } public boolean isContinue () {return isContinue; } public void setContinue (boolean isContinue) {this.iscontinue = isContinue; } elemen publik getele () {return ele; } public void setele (elemen ele) {this.ele = ele; } public Basenode getNode () {return node; } public void setNode (node basenode) {this.node = node; }}} import org.dom4j.Element;import java.util.HashMap;import java.util.Map;/** * Abstract node* @author rongdi */public abstract class BaseNode { public abstract boolean parse(Map<String, Object> currParams, Map<String, Object> globalParams, Element ele,StringBuilder sb) throws Exception; public void pre(Map<String, Object> currParams,Map<String, Object> globalParams,Element ele,StringBuilder sb) throws Exception { } public void after(Map<String, Object> currParams,Map<String, Object> globalParams,Element ele,StringBuilder sb) throws Exception { } protected Map<String, Object> getAllParams(Map<String, Object> Currparams, peta <String, Object> GlobalParams) {MAP <String, Object> allParams = new HashMap <String, Object> (); allparams.putall (GlobalParams); allparams.putall (Currparams); mengembalikan allparams; }} import java.util.Map;import ognl.Ognl;import org.apache.commons.lang.StringUtils;import org.dom4j.Element;/** * if node* @author rongdi */public class IfNode extends BaseNode{ @Override public boolean parse(Map<String, Object> currParams, Map<String, Object> globalParams, Element ELE, StringBuilder SB) melempar Exception {// Dapatkan atribut uji if node string teststr = ele.attributeValue ("test"); tes boolean = false; coba {if (stringutils.isnotempty (testStr)) {// gabungkan variabel global dan variabel lokal peta <string, objek> allparams = getAllParams (Currparams, GlobalParams); // Gunakan ognl untuk menentukan tes true atau false = (boolean) ognl.getValue (teststr, allparams); }} catch (Exception e) {e.printstacktrace (); melempar pengecualian baru ("Parameter Operasi Juri"+teststr+"ilegal"); } if (ele.content ()! = null && ele.content (). size () == 0) {test = true; } return test; }} import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;import ognl.Ognl;import org.apache.commons.collections.MapUtils;import org.apache.commons.lang.StringUtils;import org.dom4j.element;/** Atribut node foreach adalah sebagai berikut item koleksi yang perlu dilalui. Indeks variabel yang disimpan di setiap elemen setelah melintasi koleksi. Jumlah indeks koleksi adalah seperti 0, 1, 2 ... pemisah setelah melintasi, menyambung terbuka dengan pemisah yang ditentukan. Simbol yang memulai splicing setelah traversal adalah sebagai berikut (tutup simbol yang mengakhiri splicing setelah traversal adalah sebagai berikut) */kelas publik foreachnode memperluas basenode {@override public boolean parse (peta <string, objek> Currparams, peta <string, objek> globalparams, elemen ele, stringbuilder sb) throwsicer {global naL (elemen ele, stringbuilder SB) SB); String collectionstr = ele.attributeValue ("collection"); String itemtr = ele.attributeValue ("item"); Indeks string = ele.attributeValue ("index"); String pemisah = ele.attributeValue ("pemisah"); String openstr = ele.attributeValue ("open"); String closestr = ele.attributeValue ("tutup"); if (stringutils.isempty (index)) {index = "index"; } if (stringutils.isempty (sparatorstr)) {sparatorStr = ","; } if (stringutils.isNotEmpty (openstr)) {currparams.put (attrs.while_open, openstr); } if (stringutils.isnotempty (closestr)) {currparams.put (attrs.while_close, closestr); } if (stringutils.isnotEmpty (collectionstr)) {currparams.put (attrs.while_list, collectionstr); } Currparams.put (attrs.while_separator, Separatorstr); if (index! = null) { /*** Jika ada nilai variabel loop saat ini dalam variabel lokal, itu berarti bahwa ini bukan pertama kalinya Anda memasukkan label loop. Hapus tag Mulai * dan tambahkan 1 ke nilai variabel lokal */ if (currparams.get (index)! = Null) {currparams.remove (attrs.while_start); Currparams.put (indeks+"_", (integer) Currparams.get (index+"_")+1); } else {// Pertama kali Anda memasukkan label loop Currparams.put (attrs.while_start, true); Currparams.put (indeks+"_", 0); } Currparams.put (index, (integer) currparams.get (index+"_")); } kondisi boolean = true; Peta <String, Object> AllParams = getAllParams (Currparams, GlobalParams); Koleksi Objek = NULL; if (stringutils.isnotempty (collectionstr)) {// Dapatkan koleksi menjadi koleksi loop = ognl.getValue (collectionstr, allparams); // Jika properti koleksi tidak kosong, tetapi kondisinya nol, kondisi batas ditambahkan secara default jika (stringutils.isempty (conditionstr)) {// Di sini saya hanya akan menggunakan koleksi untuk menunjukkannya. Anda juga dapat menambahkan array, tetapi cukup ubah ke .length if (Collection instanceof list) {conditionstr = index+"_ <"+collectionstr+". Size ()"; } else if (collection instance dari peta) {peta peta = (peta) koleksi; Set set = map.entryset (); Daftar Daftar = Daftar Array baru (Set); allparams.put ("_ list_", daftar); conditionstr = index+"_ <_ list _"+". size ()"; }}} Currparams.remove (attrs.while_end); if (stringutils.isnotempty (conditionStr)) {// nilai kondisi perhitungan kondisi = (boolean) ognl.getValue (conditionstr, allparams); Peta <string, object> tempmap = hashmap baru <> (); tempmap.putall (allparams); tempmap.put (index+"_", (integer) currparams.get (index+"_")+1); Currparams.put (attrs.while_end ,! (boolean) ognl.getValue (conditionstr, tempmap)); } bendera boolean = true; Currparams.put (attrs.while_index, index); Currparams.put (attrs.while_flag, true); if (condition) {coba {if (stringutils.isnotempty (itemTr) && stringutils.isNotEmpty (collectionstr)) {nilainya nilai = null; int idx = integer.parseInt (currparams.get (index+"_"). ToString ()); if (daftar instance dari daftar) {value = ((daftar) koleksi) .get (idx); Currparams.put (itemstr, nilai); } else if (collection instance dari peta) {peta peta = (peta) koleksi; Set <map.entry <string, object >> set = map.entryset (); Daftar <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) {lempar pengecualian baru ("Dapatkan nilai dari koleksi atau peta"+currparams.get (index)+"error"+e.getMessage ()); }} else {flag = false; Destroyvars (Currparams, Index, ItemTtr); } mengembalikan bendera; } / *** Jika ini adalah pertama kalinya Anda memasukkan tag loop, eja konten terbuka* / @override public void pre (peta <string, objek> Currparams, peta <string, objek> globalparams, elemen ele, stringbuilder sb) melempar pengecualian {super.pre (Currparams, GlobalParams, Ele, SB); boolean start = maputils.getboolean (Currparams, attrs.while_start, false); if (start) {string open = maputils.getString (Currparams, attrs.while_open); SB.Append (terbuka); }} / *** Jika label loop akhirnya dimasukkan, konten penutupan dieja pada akhir* / @Override public batal setelah (peta <string, objek> Currparams, peta <string, objek> globalparams, elemen ele, stringbuilder sb) melempar pengecualian {super.after (currparams, globalparams, globalparams, ele, sb); boolean end = maputils.getboolean (Currparams, attrs.while_end, false); String pemisah = maputils.getString (Currparams, attrs.while_separator); if (! end && stringutils.isnotempty (pemisah)) {sb.append (pemisah); } if (end) {string close = maputils.getString (Currparams, attrs.while_close); if (sb.tostring (). endswith (pemisah)) {sb.deleteCharat (sb.length () - 1); } SB.Append (tutup); }} // Lepaskan variabel sementara variabel void dashingvars (peta <string, object> arus, indeks string, string varstr) {currparams.remove (attrs.while_index); Currparams.remove (attrs.while_flag); Currparams.remove (attrs.while_separator); Currparams.remove (attrs.while_start); Currparams.remove (attrs.while_end); Currparams.remove (attrs.while_list); }} impor org.dom4j.element; import java.util.map; kelas publik sqlnode memperluas basenode {@override public boolean parse (peta <string, objek> Currparams, peta <string, objek> globalparams, elemen ele, stringbuilder sb) lemparan pengecualian {return return; }}import java.util.Arrays;import java.util.List;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;/** * Node Factory*/public class NodeFactory { private static Map<String,BaseNode> nodeMap = new ConcurrentHashMap<String,BaseNode>(); Daftar statis akhir pribadi <String> whilelist = arrays.aslist ("foreach"); static {nodemap.put ("if", new iFnode ()); nodemap.put ("sql", sqlnode baru ()); nodemap.put ("foreach", foreachnode baru ()); } public static boolean ishile (string elementName) {return whilelist.contains (elementName); } public static void addNode (string nodename, node basenode) {nodemap.put (nodename, node); } public static Basenode buat (string nodename) {return nodemap.get (nodeName); }}/*** Berbagai tag* @author rongdi*/class public attrs {public final static string transaksional = "transactional"; string statis akhir publik while_start = "while-start"; string statis akhir publik while_end = "while-end"; string statis akhir publik while_open = "while-open"; string statis akhir publik while_close = "while-close"; string statis akhir publik while_separator = "while-separator"; string statis akhir publik while_index = "while-index"; string statis akhir publik while_flag = "while-flag"; string statis akhir publik while_list = "while-list"; string statis akhir publik when_flag = "when-flag"; Public Static Final String Process_var = "Process-Var"; string statis final publik result_flag = "hasil-flag"; string statis final publik return_flag = "return-flag"; string statis final publik console_var = "console-var"; string statis akhir publik do = "do"; Indeks String Statis Akhir Publik = "Indeks"; Kondisi string statis akhir publik = "kondisi"; name string statis final publik = "name"; nilai string statis akhir publik = "nilai"; Tipe string akhir public static = "type"; format string final statis publik = "format"; string akhir statis publik if = "if"; string akhir statis publik lain = "else"; File String Statis Akhir Publik = "File"; Tanggal String Akhir Statis Publik = "Tanggal"; string final statis publik sekarang = "sekarang"; string final public static decimal = "decimal"; ID String Akhir Statis Publik = "ID"; public static final string params = "params"; target string final statis publik = "target"; string final statis publik single = "single"; public final string paging = "paging"; String final statis publik desc = "desc"; string final statis public break = "break"; String akhir statis publik Lanjutkan = "Lanjutkan"; Public Static Final String Collection = "Collection"; string final statis publik var = "var"; Public Static Final String Executor = "Executor-1"; string final statis public rollback_flag = "rollback-flag"; Layanan String Akhir Statis Publik = "Layanan"; Public Static Final String Ref = "Ref"; Public Static Final String Bizs = "Bizs"; Judul String Akhir Statis Publik = "Judul"; kolom string final statis publik = "kolom"; Public Static Final String Curruser = "Curruser"; public static string final CurrperM = "CurrperM"; string final public static Task_executor = "Taskexecutor"; Public Static Final String Delimiter = "Pembatas"; Public Static Final String OperName = "OperName"; } Currparams.remove (varstr); Currparams.remove (indeks); Currparams.remove (index+"_"); }}Lampirkan file pom
<Project xmlns = "http://maven.apache.org/pom/4.0.0" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" xsi: schemalocation = "http:/maven.romp.romp.romp. http://maven.apache.org/maven-v4_0_0.xsd "> <podelversion> 4.0.0 </podelversion> <groupid> com.rd </groupid> <ArTifactId> Parser </arttifactid> <packaging> Jar </packaging> <TROMING> 1.0-Snapsh </artifacsh> <packaging> </packaging> <TROMINGRE> </VERSIONS </ARTIFACTID> <packaging> Jar </packaging> <ArtiFR Versi> 1.0 <rerl> http://maven.apache.org </rerl> <dependencies> <dependency> <groupid> DOM4J </sroupid> <Artifactid> DOM4J </artifactid> <version> 1.6.1 </version> </dependency> <dependency> <sroupid> Opensymphony </Groupt> </dependency> <grouplency> <groupid> Opensymphony </Groupp <version>2.6.11</version> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependency> </dependencies> <build> <resources> <resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </cert> </resource> <peneranggaan> <Rectory> SRC/Main/Resources </Directory> <clude> <certed> **/*</include> </sumberce> </Resources> </testResources> <TestResources> <TesCource> <recrectory> $ {Project.basedir}/SRC/SRC/SRC/SRCC/TESTORY> <RECTORY> $ {Project.basedir}/SRC/SRC/SRCC/SRCC/TESTORY> <Rectory> $ {Project.basedIr}/src/test/sumber daya </cirectory> </testResource> </testResources> <dlugin> <groupid> org.apache.maven.plugins </groupid> <ArtifactId> <11118-compiler-compiler-compiler-compiler </artifactid> <cortifact> <target> 1.8 </target> <coding> UTF-8 </coding> </configuration> </lugin> </lugin> </build> </poject>Metode di atas untuk mengimplementasikan SQL Dinamis MyBatis sendiri adalah semua konten yang telah saya bagikan dengan Anda. Saya harap Anda dapat memberi Anda referensi dan saya harap Anda dapat mendukung wulin.com lebih lanjut.