Я обнаружил, что действительно сложно настаивать на написании блога, и различные причины не приведут к необходимости заботиться о блоге. Первоначально я планировал написать реализацию 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 <if test = "widgetcodes! = null"> где pageWidgetCode в <foreach collection = "widgetCodes" item = "item" index = "index" open = "(" seperator = "," close = ")"> <if test = "index == 0"> #{item} </if> <foreece = "bs" bs "bs" bs "bs" bs " index = "index1" open = "(" separator = "," close = ")"> #{b} </foreach> </foreach> </if> <if test = "a! = null"> и a = #{a} </if>Чтобы реализовать SQL для анализа приведенного выше примера, одна из трудностей аналогична тому, как определить истинные или ложные условия в атрибуте теста. Тем не менее, эта трудность больше находится перед выражением Ognl, изученной в Struts2. Я не знаю, столкнулся ли друг с довольно странным явлением, то есть иногда следующее выражение написано в динамике Mybatis, но когда n = 0, оно фактически соответствует условию, то есть значение в тесте является ложным, а 0 не может соответствовать условиям этого выражения. Это причина для библиотеки Ognl. Нет никакого способа, которым это просто играет, просто помните это как особую ситуацию
тест = "n! = null и n! = ''"
Выражение ognl очень удобно использовать следующим образом
import java.util.hashmap; import java.util.map; import ognl.ognl; public class ognltest {// Вывод Результат: False Public Static void Main (String [] args) выбрасывает исключение {string con1 = "n! = null и n! = '' '"; Map <string, object> root = new hashmap <> (); root.put ("n", 0); System.out.println (ognl.getValue (con1, root)); }}Чтобы внедрить SQL для анализа приведенного выше примера, вторая сложность заключается в том, что, хотя этот SQL покрыт слоем XML, это стандартный SQL, следующим образом
<sql> удалить из pl_pagewidget <if test = "widgetcodes! = null">, где pagewidgetCode в <foreach collection = "widgetCodes" item = "item" index = "open =" ("seperator =", "close =") "> <if test =" index == 0 "> #{item} </if> <fo> <fo> <fo> <for> <for> <fo> <fo> <fo> <fo> <fo> <fo> <fo> <fo> <fo> <fo> <fo> <for> <fo> <fo> <fo> index = "index1" open = "(" sepeator = "," close = ")"> #{b} </foreach> </foreach> </if> <if test = "a! = null"> и a = #{a} </if> </sql>Тем не менее, анализ вышеупомянутого XML отличается от наших обычных. Этот XML представляет собой смесь тегов и текста. Обычно мы должны редко использовать анализ этого XML в разработке. Тем не менее, обычно используемый инструмент для анализа XML DOM4J фактически может очень хорошо проанализировать этот вид SQL, но он редко используется. Метод Content () класса элементов может вернуть коллекцию узлов, а затем пройти эту коллекцию и судить тип каждого узла. После решения этих двух ключевых моментов вам нужно только добавить немного трюка, чтобы проанализировать этот динамический SQL.
Трюк, который я использовал, был вдохновлен форматом синтаксиса Java. Например, в Java существуют локальные переменные и глобальные переменные, и ситуация с передачей ссылки не рассматривается. Если глобальная переменная int i = 1; Глобальная переменная передается в метод и затем изменяется в методе. В методе вы видите измененное значение, но то, что вы видите вне метода, все еще 1. Фактически, вы должны знать это явление после изучения Java. Кроме того, когда метод называется, вы можете увидеть глобальные переменные и локальные переменные в методе. После того, как вызов метода будет завершен, локальные переменные будут очищены и выпущены (пожалуйста, будьте рады увидеть сборщик мусора). Я представил их и напрямую добавил код
Импорт java.io.stringReader; import java.text.simpledateformat; import java.util.arrays; import java.util.date; импорт java.util.hashmap; импорт java.util.list; importa.util.map; import java.til.regex.mather; org.apache.commons.collections.maputils; import org.apache.commons.lang.stringutils; import org.dom4j.document; импорт org.dom4j.element; импорт org.dom4j.node; импорт org.dom4j.text; импорт org.dom4j.io.saxreder; com.rd.sql.basenode; import com.rd.sql.nodefactory; public class sqlparser {private map <string, object> currparams = new hashmap <string, object> (); /** Удалить из pl_pagewidget <if test = "widgetcodes! = null"> где pagewidgetCode в <foreach collection = "didgetcodes" item = "item" index = "index" open = "(" sepreator = "," close = ")"> <if test = index == 0 "> #{Item} </if> <foreece collect index = "index1" open = "(" sepeator = "," close = ")"> #{b} </foreach> </foreach> </if> <if test = "a! = null"> и a = #{a} </if> */public void main (String [] args) throws exection {string, object> map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = map = new hasmap <) map.put ("widgetcodes", arrays.aslist ("1", "2")); map.put ("bs", arrays.aslist ("3", "4")); map.put ("a", 1); Sqlparser parser = new sqlparser (); System.out .println(parser.parser("delete from pl_pagewidget/n" + "/t<if test=/"widgetcodes != null/">/n" + "/t/twhere pagewidgetcode in/n" + "/t/t<foreach collection=/"widgetcodes/" item=/"item/" index=/"index/" open=/"(/" separator=/",/" close=/")/">/n" + "/t/t <if test=/"index == 0/">/n" + "/t/t #{item}/n" + "/t/t </if>/n" + "/t/t <foreach collection=/"bs/" item=/"b/" index=/"index1/" open=/"(/" separator =/",/" close =/")/">/n " +"/t/t/t #{b}/n " +"/t/t </foreach>/n " +"/t/t </foreach>/n " +"/t </if>/n " +"/t <if test =/a! "/t </if>/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 для входной динамики SQL XML = "<SQL>"+XML+"</sql>"; SaxReader Reader = New SaxReader (false); Document Document = reader.read (new StringReader (XML)); Element = document.getRootelement (); Map <string, object> currParams = new HashMap <String, Object> (); StringBuilder SB = new StringBuilder (); // запустить проведение проведения (элемент, currarams, params, sb); вернуть sb.toString (); } /** * Используйте рекурсивный анализатор, чтобы проанализировать динамический SQL * @param ele1 xml Tag, чтобы проанализировать * @param currparams * @param globalparams * @param sb * @throws исключение * /private void parserelement (element ele1, map <string, объект> currparms, map <string> globalparement, stringbu, stringbu) Проповедовать узел, например, проанализировать узел, если тест определяет TRUE, он возвращает true. Tempval val = parseroneelement (currararams, globalparams, ele1, sb); // объект абстрактного узла, проанализированного узла узла BaseNode = val.getNode (); /*** Фактически, утверждение выше этого предложения только анализирует тег XML и не анализирует контент в теге. Здесь * означает, что перед анализом содержания, если есть предварительное операцию, сделайте некоторое предварительное операцию */ node.pre (currarams, globalparams, ele1, sb); // Защита, например, должен ли контент в узле все еще анализироваться, если результатом теста является истинным логическим флагом = val.iscontinue (); // Получить коллекцию всех дочерних узлов под этим узлом, включая нормальный текстовый список <node> nodes = ele1.content (); if (flag &&! nodes.isempty ()) { /*** Это означает, что вы хотите дополнительно проанализировать контент в узле. Вы можете сравнить узел с оболочкой метода* Содержание внутри аналогично конкретным операторам в методе. Прежде чем начать анализировать содержимое узла* Создайте контейнер с локальными параметрами под этим узлом. Наиболее удобным является, конечно, карта */ map <string, object> params = new hashmap <string, object> (); /*** Поместите локальные параметры, передаваемые снаружи непосредственно в контейнер, поскольку параметры в этом примере являются общими типами данных* Там не будет ссылочного типа, так что это эквивалентно копии. Чтобы не повлиять на объект, переданный снаружи*, вы можете сравнить случай, когда метод вызывает входящие параметры*/ params.putall (currarams); // цикл всех дочерних узлов для (int i = 0; i <nodes.size ();) {node n = nodes.get (i); // Если узел - это нормальный текст if (n encessOf text) {string text = ((text) n) .getStringValue (); if (stringutils.isnotempty (text.trim ())) {// обучить текст, например, обработка #{xx}, напрямую заменить $ {yy} на реальное значение, передаваемое в sb.append (handtext (text, params, globalparams)); } i ++; } else if (n encessOf element) {element e1 = (element) n; // рекурсивно проанализировать XML -элементы дефицита прокладок (E1, Params, GlobalParams, SB); // Если флаг петли не правда, проанализируйте следующий тег // Это означает, что вам необходимо многократно анализировать тег цикла, то я не буду менять, в противном случае продолжать обрабатывать следующий элемент Boolean Whise_flag = maputils.getboolean (params, attrs.while_flag, false); if (! while_flag ||! nodefactory.iswhile (n.getName ()) || e1.attributevalue (attrs.index) == null ||! e1.attributevalue (attrs.index) .equals (params.get (attrs.while_index))) {i ++; }}} // Что мне делать после узла узла. // переработка текущего параметра параметров параметров Params.Clear (); params = null; }} /**! Integer Index = null; if (stringutils.isnotempty (indexstr)) {index = maputils.getInteger (params, indexstr); } // match #{a} string parameter reg1 = "( #// {) (// w+) (//})"; // Сопоставьте параметр $ {a} string reg2 = "(// $ // {) (// w+) (//})"; Шаблон P1 = pattern.compile (reg1); Matchter M1 = P1.matcher (str); Шаблон P2 = pattern.compile (reg2); Matchter M2 = P2.matcher (str); String whilelist = maputils.getstring (params, attrs.while_list); Map <string, object> allparams = getallParams (params, globalparams); while (m1.find ()) {string tmpkey = m1.group (2); String key = whilelist == null? Tmpkey: (в то время как+"_"+tmpkey); key = index == null? Ключ: (ключ+индекс); String rekey = "#{"+key+"}"; // Если в цикле, аналогичном Foreach, вам может потребоваться заменить параметр #{xx} на #{xx_0}, #{xx_1} str = str.replace (m1.group (0), rekey); currararams.put (key, allparams.get (tmpkey)); } while (m2.find ()) {string tmpkey = m2.group (2); Значение объекта = allparams.get (tmpkey); if (value! = null) {str = str.replace (m2.group (0), getValue (value)); }} return str; } частная строка getValue (значение объекта) {string result = ""; if (value ancessionof date) {simpledateformat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); result = sdf.format ((date) значение); } else {result = string.valueof (value); } return Result; } private map <string, object> getAllParams (map <string, object> currParams, map <string, object> globalparams) {map <string, object> allparams = new hashmap <string, object> (); allparams.putall (GlobalParams); allparams.putall (currarams); вернуть AllParams; } // Проанализируйте элемент XML Private Tempval parseroneElement (map <string, object> currarams, map <string, object> globalparams, element ele, stringbuilder sb), бросает исключение {// Получить имя тега xml string elename = ele.getname (); // Это продолжается после анализа узла? Если вы столкнетесь с узлом, как если бы вам не нужно определить, пусто, тест. логический iscontinue = false; // объявить абстрактный узел базовый узел = null; if (stringUtils.isnotempty (Elename)) {// Использовать фабрику узла, чтобы получить объект узла на основе имени узла, например, если узел или узел узел = nodefactory.create (Elename); // Проанализируйте этот узел и возвращайте, должен ли контент в узле все еще проанализировать iscontinue = node.parse (currararams, globalparams, ele, sb); } вернуть new Tempval (iscontinue, ele, node); } public map <string, object> getParams () {return currParams; } / *** Инкапсулировать результат после того, как элемент XML проанализирован* @author rongdi* / final static class tempval {private boolean iscontinue; частный элемент Ele; частный узел BaseNode; Public Tempval (Boolean Iscontinue, Element Ele, BaseNode Node) {this.iscontinue = iscontinue; this.ele = ele; this.node = node; } public boolean iscontinue () {return iscontinue; } public void setContinue (boolean iscontinue) {this.iscontinue = iscontinue; } public element getele () {return ele; } public void setele (element 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 rable -boolean parse (map <string> currparams, map <String, Object> Global Pparams, элемент Elen, StringBu, stringBu -SB); public void pre (map <string, object> currparams, map <string, object> globalparams, element ele, stringbuilder sb) throws exection {} public void после (map <string> currParams, map <string> globalparams, element ele, stringbuilder sb) throws exception {} protected map, объект> getAllpar (objectParpArMs (объект> gateAllpar (objectPar. Map <string, object> globalparams) {map <string, object> allparams = new hashmap <string, object> (); allparams.putall (GlobalParams); allparams.putall (currarams); вернуть 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) бросает исключение {// Получить атрибут теста if node string teststr = ele.attributevalue ("test"); логический тест = false; try {if (stringUtils.isnotempty (teststr)) {// слияние глобальных переменных и локальных переменных map <string, object> allparams = getallParams (currarams, globalparams); // Использовать ognl для определения TRUE или FALSE TEST = (BOOLEAN) ognl.getValue (Teststr, AllParams); }} catch (Exception e) {e.printstackTrace (); бросить новое исключение («Параметры операции судьи»+teststr+«незаконно»); } if (ele.content ()! = null && ele.content (). size () == 0) {test = test = true; } return Test; }} Импорт java.util.arraylist; import java.util.hashmap; import java.util.list; импорт java.util.map; import java.util.set; import ognl.ognl; import org.apache.commons.collections.maputils; импорт org..pache. Атрибуты узла Foreach являются следующими элементом сбора, который необходимо пройти. Индекс переменной, хранящийся в каждом элементе после пересечения коллекции. Номер индекса коллекции такой, как 0, 1, 2 ... сепаратор после прохождения, сплайсинг открывается с указанным сепаратором. Символы, которые начинают сплайсинг после обхода, заключаются в следующем (закройте символы, которые заканчивают сплайсинг после обхода, следующие) */public Class foreachnode Extens BaseNode {@Override Public Boolean Parse (Map <String> CurrParams, Map <String> Global Pparams, Element Ele, STRESBUILDER SU). String CollectionStr = ele.AttributeValue ("Collection"); String itemstr = ele.attributevalue ("item"); String Index = ele.AttributeValue ("index"); String seperators = ele.attributevalue ("sepreatator"); String openStr = ele.attributevalue ("open"); String closeStr = ele.attributevalue ("close"); if (stringutils.isempty (index)) {index = "index"; } if (stringUtils.isempty (seperatorstr)) {separatorstr = ","; } if (stringUtils.isnotempty (openstr)) {currParams.put (attrs.while_open, openstr); } if (stringUtils.isnotempty (closestr)) {currparams.put (attrs.while_close, useestry); } if (stringUtils.isnotempty (collectionstr)) {currParams.put (attrs.while_list, collectionstr); } currParams.put (attrs.while_separator, separatorstr); if (index! = null) { /*** Если есть значение текущей переменной цикла в локальной переменной, это означает, что это не первый раз, когда вы ввели метку цикла. Удалите The Start Tag * и добавьте 1 в локальное значение переменной */ if (currarams.get (index)! = Null) {currparams.remove (attrs.while_start); currparams.put (index+"_", (целое число) currparams.get (index+"_")+1); } else {// первый раз, когда вы вводите метку цикла CurrParams.put (attrs.while_start, true); currparams.put (index+"_", 0); } currParams.put (index, (Integer) currParams.get (index+"_")); } логическое условие = true; Map <string, object> allparams = getallparams (currararams, globalparams); Сбор объектов = null; if (stringUtils.isnotempty (collectionstr)) {// Получить коллекцию, чтобы быть циклевой Collection = ognl.getValue (CollectionStr, AllParams); // Если свойство сбора не является пустым, но условие является нулевым, граничное условие добавляется по умолчанию, если (stringUtils.isempty (conditionstr)) {// здесь я просто использую коллекцию, чтобы продемонстрировать ее. Вы также можете добавить массив, но просто изменить его на .length if (exactionOf incessionOf) {condityStr = index+"_ <"+collectionStr+". Size ()"; } else if (collection encessionof map) {map map = (map) collection; SET SET = map.EntrySet (); Список списка = новый ArrayList (set); allparams.put ("_ dist_", list); ConditionSt = index+"_ <_ List _"+". size ()"; }}} currParams.remove (attrs.while_end); if (stringutils.isnotempty (conditionstr)) {// значение условия расчета = (boolean) ognl.getValue (conditionStr, allParams); Map <string, object> tempmap = new hashmap <> (); tempmap.putall (allparams); tempmap.put (index+"_", (Integer) currParams.get (index+"_")+1); currararams.put (attrs.while_end ,! (логический) ognl.getvalue (conditionstr, tempmap)); } логический флаг = true; currparams.put (attrs.while_index, index); currararams.put (attrs.while_flag, true); if (condition) {try {if (stringutils.isnotempty (itemtr) && stringutils.isnotempty (collectionstr)) {object value = null; int idx = integer.parseInt (currParams.get (index+"_"). toString ()); if (exantection exanceOf list) {value = ((list) collection) .get (idx); currararams.put (itemstr, значение); } else if (collection encessionof map) {map map = (map) collection; SET <Map.Entry <String, Object >> set = map.EntrySet (); List <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) {Throw New Exception ("получить значение из коллекции или карты"+currParams.get (index)+"ошибка"+e.getMessage ()); }} else {flag = false; Destroyvars (Currararams, Index, itemstr); } вернуть флаг; } / *** Если это первый раз, когда вы вводите тег цикла, заклинайте содержимое Open* / @Override public void pre (map <string, объект> currParams, map <строка, объект> globalparams, element ele, stringbuilder sb). boolean start = maputils.getboolean (currparams, attrs.while_start, false); if (start) {string open = maputils.getString (currParams, attrs.while_open); SB.Append (Open); }} / *** Если метка цикла наконец введена, содержание закрытия пишет в конце* / @override public void после (map <string, object> currarams, map <string, объект> GlobalParams, Element ele, Stringbuilder SB) бросает исключение {super.after (currparams, globalparams, ele, sb); boolean end = maputils.getboolean (currararams, attrs.while_end, false); String seperator = maputils.getstring (currararams, attrs.while_separator); if (! end && stringutils.isnotempty (seperator)) {sb.append (seperator); } if (end) {string clond = maputils.getString (currParams, attrs.while_close); if (sb.toString (). Endswith (sepreator)) {sb.deleteCharat (sb.length () - 1); } sb.Append (close); }} // Отпустите временную переменную private void destressvars (map <string, object> currarams, string index, string varstr) {currparams.remove (attrs.while_index); currararams.remove (attrs.while_flag); currararams.remove (attrs.while_separator); currararams.remove (attrs.while_start); currararams.remove (attrs.while_end); currparams.remove (attrs.while_list); }} import org.dom4j.element; import java.util.map; public class sqlnode extends basenode {@override public boolean parse (map <string, object> currarams, map <string> globalparams, element ele, stringbuilder sb) throws excecent {return true; }} 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> ();); частный окончательный статический список <string> whilelist = arrays.aslist ("foreach"); static {nodemap.put ("if", new ifnode ()); nodemap.put ("sql", new sqlnode ()); nodemap.put ("foreach", new Foreachnode ()); } public static boolean iswhile (string elementName) {return whilelist.contains (elementName); } public static void AddNode (String nodename, базовый узел) {nodemap.put (nodeName, node); } public static baseNode create (string nodename) {return nodemap.get (nodeName); }}/*** Различные теги* @author rongdi*/public class attrs {public final Static String Transactional = "Transactional"; публичная окончательная статическая строка while_start = "while-start"; публичная окончательная статическая строка while_end = "while-end"; публичная окончательная статическая строка while_open = "while-open"; публичная окончательная статическая строка while_close = "while-close"; публичная окончательная статическая строка while_separator = "while-sparator"; публичная окончательная статическая строка while_index = "while-index"; публичная окончательная статическая строка while_flag = "while-flag"; публичная окончательная статическая строка while_list = "while-list"; публичная окончательная статическая строка when_flag = "Когда-флаг"; Public Static Final String Process_var = "Process-Var"; публичная окончательная статическая строка result_flag = "Результат-флаг"; публичная окончательная статическая строка return_flag = "return-flag"; public final Static String console_var = "Консоль-вар"; публичная окончательная статическая строка do = "do"; public final Static String Index = "index"; публичная конечная статическая строка условия = "условие"; public final Static String name = "name"; публичная конечная статическая строка value = "value"; Public Static Final String Type = "type"; Public Static Final String Format = "format"; публичная статическая конечная строка if = "if"; публичная статическая конечная строка else = "else"; public final Static String file = "file"; Общественная статическая конечная строката date = "date"; публичная статическая конечная строка сейчас = "сейчас"; публичная статическая конечная строка Decimal = "Decimal"; Public Static Final String id = "id"; публичная статическая конечная строка params = "params"; Public Static Final String Target = "target"; Public Static Final String Single = "Single"; Public Static Final String Paging = "Paging"; публичная статическая конечная строка desc = "desc"; Public Static Final Final String Break = "Break"; Public Static Final String продолжите = "Продолжить"; Public Static Final String Collection = "Collection"; публичная статическая конечная строка var = "var"; Public Static Final String executor = "Исполнитель-1"; Public Static Final String Rolback_flag = "Rollback-Flag"; Public Static Final String Service = "Service"; публичная статическая конечная строка ref = "ref"; Public Static Final String Bizs = "Bizs"; Public Static Final String Tills = "titles"; Public Static Final String Columns = "Columns"; Public Static Final String Curruser = "curruser"; Public Static Final String currperm = "currperm"; public Static Final String task_executor = "taskexecutor"; Public Static Final String DeLimiter = "delimiter"; публичная статическая конечная строка opername = "opername"; } currParams.remove (varstr); currararams.remove (index); currparams.remove (index+"_"); }}Прикрепите файл POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.rd</groupId> <artifactId>parser</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>myparser</name> <URL> http://maven.apache.org </url> <dependencies> <dependency> <groupid> dom4j </groupid> <artifactid> dom4j </artifactid> <sersion> 1.6.1 </version> </arderency> <dehyed> <groupid> opensymphony </artifactid> ortifact> ortifact> </зависимость> <groupid> opensymphony </artifactid> </зависимость> <groupid> opensymphony1 <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> <depervice> <groupid> junit </groupid> <artifactid> junit </artifactid> <serse> 3.8.1 </version> <crappope> test </scope> </depertive> </depertive> </depertive> <buld> <resources> <resource> <resource> <Catelectory> src/main/java </directory> <clact> <clact>*. </incluct> </resource> <sursce> <cistectory> src/main/resources </directory> <clact> <clact> **/*</includ> </resource> </resources> </testresources> <testresources> <testresource> <ficeletory> $ {project.basedir}/src/testrce> testrce> testrce> testrce> testrce> testr <directory>${project.basedir}/src/test/resources</directory> </testResource> </testResources> <plugins> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <Target> 1.8 </target> <concoding> UTF-8 </encoding> </configuration> </plugin> </plugins> </build> </project>Приведенный выше метод для реализации Mybatis Dynamic SQL самостоятельно - это весь контент, которым я поделился с вами. Я надеюсь, что вы можете дать вам ссылку, и я надеюсь, что вы сможете поддержать Wulin.com больше.