Descubrí que es realmente difícil insistir en escribir un blog, y varias razones no llevarán a la necesidad de cuidar el blog. Originalmente planeé escribir una implementación de bricolaje de ORM y ver la hora. Prefiero implementar primero un SQL dinámico y agregar la implementación completa de ORM la próxima vez que tenga tiempo.
Las personas que han usado mybatis probablemente estén familiarizadas con SQL dinámico. Si no lo ha usado, solo eche un vistazo a la diversión. La primera vez que entré en contacto con MySQL fue cuando estaba en mi último año. En ese momento, pensé que Dynamic SQL era muy increíble y flexible. Siempre quise descubrir cómo implementarlo. Aunque podría escribir marcos de IOC, MVC y ORM simples en ese momento (imitar mybaits pero no hay una parte dinámica de SQL), todavía no pude encontrar dónde implementar el SQL dinámico en el núcleo de MyBatis y cómo implementarlo. Tal vez el código estaba demasiado enredado y no pude entenderlo en absoluto. Hasta ahora, no tenía el coraje de leer la parte dinámica de SQL de MyBatis. Tal vez nací con un asombro inexplicable de algoritmos.
Hace unos años, debido a que quería crear una plataforma de configuración y quería usar un lenguaje de análisis para reemplazar la implementación de Java, lo que permitió al personal de configuración escribir fácilmente una pequeña cantidad de código en la página para implementar una lógica comercial compleja (incluidas las operaciones de la base de datos). En ese momento, Java ya tenía un motor de análisis JS, pero la mayoría de la gente dijo que la eficiencia era demasiado baja. Si no sabía de qué estaba loco, pensé en implementar un lenguaje de análisis yo mismo. Sin embargo, siempre he soñado con darme cuenta de mi propio idioma. Es más fácil comenzar con idiomas analíticos que los idiomas compilados, por lo que comencé a hacerlo decisivamente. Después de escribirlo, me di cuenta de que mi implementación probablemente no sea tan eficiente como el motor JS en ese momento. En ese momento, era muy joven y simple. La implementación dinámica de SQL de la que estoy hablando hoy está realmente inspirada en el lenguaje de análisis en ese momento.
Hablemos de SQL dinámico sin decir muchas tonterías. Consulte el siguiente ejemplo. Primero, declaro que el ejemplo aquí no es una forma correcta de escribir SQL. Solo quiero escribir una estructura anidada que sea lo más compleja posible. Si se implementa esta compleja situación, entonces es aún más difícil simplificarla.
Eliminar de pl_pagewidget <if test = "widgetCodes! = null"> donde pageWidgetCode en <foreach Collection = "widgetCodes" item = "item" index = "index" abre = "(" separator = "," close = ")"> <if "index == 0"> #{item} </if> <foreach Collection = "bs" item "b" b "b" Open = "(" Separator = "," Close = ")"> #{B} </FOREACH> </FOREACHE> </if> <if test = "a! = null"> y a = #{a} </fif>Para implementar SQL para analizar el ejemplo anterior, una de las dificultades es similar a cómo determinar las condiciones verdaderas o falsas en el atributo de prueba. Sin embargo, esta dificultad está más frente a la expresión de OGNL aprendida en Struts2. No sé si un amigo se ha encontrado con un fenómeno bastante extraño, es decir, a veces la siguiente expresión está escrita en myBatis Dynamic SQL, pero cuando n = 0, en realidad cumple con la condición, es decir, el valor en la prueba es falso y 0 no puede cumplir con las condiciones de esta expresión. Esta es la razón de la biblioteca OGNL. No hay forma de que juegue así, solo recuerda como una situación especial.
test = "n! = null y n! = ''"
La expresión de OGNL es muy conveniente de usar de la siguiente manera
import java.util.hashmap; import java.util.map; import ognl.ognl; public class ognltest {// resultado de salida: falso público estático void main (string [] args) arroja excepción {String con1 = "n! = null y n! = ''"; Map <string, object> root = new HashMap <> (); root.put ("n", 0); System.out.println (ognl.getValue (con1, raíz)); }}Para implementar SQL para analizar el ejemplo anterior, la segunda dificultad es que aunque este SQL está cubierto con una capa de XML, es un SQL estándar, como sigue
<sql> Eliminar de pl_pagewidget <if test = "widgetCodes! = null"> donde pageWidgetCode en <foreach colección = "widgetCodes" item = "item" index = "index" abre = "(" separator = "," close = ")"> <if test = "index == 0"> #{item} </if> <foreach Collect Collection "Bs" ítem " index = "index1" open = "(" separator = "," Close = ")"> #{b} </ foreach> </ foreach> </if> <if test = "a! = null"> y a = #{a} </if> </sql>Sin embargo, analizar el XML anterior es diferente de nuestros habituales. Este XML es una mezcla de etiquetas y texto. Normalmente, rara vez deberíamos usar este XML en el desarrollo. Sin embargo, la herramienta comúnmente utilizada para analizar XML DOM4J en realidad puede analizar muy bien este tipo de SQL, pero rara vez se usa. El método Content () de la clase de elementos puede devolver una colección de nodos y luego atravesar esta colección y juzgar el tipo de cada nodo. Después de resolver estos dos puntos clave, solo necesita agregar un pequeño truco para analizar este SQL dinámico.
El truco que utilicé se inspiró en el formato de sintaxis Java. Por ejemplo, hay variables locales y variables globales en Java, y no se considera la situación de aprobación de referencia. Si la variable global int i = 1; La variable global se pasa al método y luego se modifica en el método. Lo que ve en el método es el valor cambiado, pero lo que ve fuera del método sigue siendo 1. De hecho, debe conocer este fenómeno después de aprender Java. Además, cuando se llama al método, puede ver variables globales y variables locales en el método. Después de que se termine la llamada del método, las variables locales se borrarán y lanzarán (esté encantado de ver el recolector de basura). Los he introducido y agregué directamente el código
import java.io.StringReader; import java.text.simpledateFormat; import java.util.arras; import java.util.date; import java.util.hashmap; import java.util.list; import java.util.map; import java.util.regex; import java.utileutil. org.apache.commons.collections.maputils; import org.apache.commons.lang.stringutils; import og.dom4j.document; import org.dom4j.element; importar org.dom4j.node; import odom4j.text; import org.dom4j.io.saxreer; import.rd.rd.sqls; com.rd.sql.basenode; import com.rd.sql.nodeFactory; public class sqlParser {private map <string, object> CurrParams = new Hashmap <String, Object> (); /** Eliminar de pl_pagewidget <if test = "widgetCodes! = null"> donde pageWidgetCode en <foreach collection = "widgetCodes" item = "item" index = "index" open = "(" separator = "," close = ")"> <if "index =" index == 0 "> #{item} </if> <foreach Collection =" bs "item" bs "bs" b "b" b "b" b "b" b "b" b "b" b "b" b "b" b " Open = "(" Separator = "," Close = ")"> #{B} </FOREACH> </FOREACHE> </if> <if test = "a! = null"> y a = #{a} *if> */public static void main (string [] lanza excepción {string <string> map = new hastmap <String, object> (); 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 ("eliminar de pl_pagewidget/n" + "/t <if test =/" widgetCodes! = Null/">/n" + "/t/t/twhere pagewidgetCode in/n" + "/t/t <foreach Collection =/" widgetcodes/"item =" item/"Índice =/" índice/"ineper 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=/",/" cerrar =/")/">/n " +"/t/t/t #{b}/n " +"/t/t </foreach>/n " +"/t/t/t </foreach>/n " +"/t </if>/n " +"/t <if test =/"a! = null/">/n " +"/t/t/t a = #{a {a {n " mapa)); System.out.println (parser.getParams ()); } public String parser (String xml, map <string, object> params) lanza la excepción {// xml = "<? xml versión =/" 1.0/"encoding =/" utf-8/"?>"+xml; // Establecer una capa de etiquetas XML para la entrada dinámica sql xml = "<sql>"+xml+"</sql>"; Saxreader lector = new SaxReader (falso); Documento documento = Reader.read (new StringReader (xml)); Elemento elemento = document.getRootElement (); MAP <String, Object> CurrParams = new Hashmap <String, Object> (); StringBuilder sb = new StringBuilder (); // Iniciar ParserElement (Elemento, CurrParams, Params, SB); return sb.ToString (); } / ** * Use el analizador recursivo para analizar SQL * @param ele1 xml la etiqueta para ser analizado * @param curvparams * @param globalparams * @param sb * @throws excepción * / private void parserelement Un nodo, por ejemplo, analiza un nodo if, si la prueba determina verdadero, devuelve verdadero. Tempval val = parseroneElement (CurrParams, GlobalParams, ELE1, SB); // El objeto de nodo abstracto del nodo Basenode parsed nodo = val.getNode (); /*** De hecho, la declaración sobre esta oración solo analiza la etiqueta XML y no analiza el contenido en la etiqueta. Aquí * significa que antes de analizar el contenido, si hay una preoperación, haga alguna preoperación */ node.pre (CurrParams, GlobalParams, ELE1, SB); // Defender si el contenido en el nodo aún debe analizarse, por ejemplo, si el resultado de la prueba es verdadero Boolean Flag = val.Iscontinue (); // Obtenga una colección de todos los nodos infantiles en este nodo, incluida la lista de texto normal <node> nodos = ele1.content (); if (flag &&! Nodes.isEmpty ()) { /*** Esto significa que desea analizar aún más el contenido en el nodo. Puede comparar el nodo en el shell de un método* El contenido en el interior es análogo a las declaraciones específicas en el método. Antes de comenzar a analizar el contenido del nodo*, cree un contenedor con parámetros locales en este nodo. El más conveniente es, por supuesto, map */ map <string, object> params = new Hashmap <String, Object> (); /*** Ponga los parámetros locales pasados afuera directamente en el contenedor, porque los parámetros en este ejemplo son tipos de datos comunes* No habrá tipo de referencia, por lo que esto es equivalente a una copia. Para no afectar el objeto pasado en el exterior*, puede comparar el caso donde el método llama los parámetros entrantes*/ params.putall (CurrParams); // bucle todos los nodos infantiles para (int i = 0; i <nodo.size ();) {nodo n = nodo.get (i); // Si el nodo es un texto normal si (n instanceof text) {string text = ((text) n) .getStringValue (); if (stringUtils.isNotEmpty (text.trim ())) {// Entrena el texto, como el procesamiento #{xx}, reemplaza directamente $ {yy} con el valor real pasado en sb.append (handtext (text, params, globalParams)); } i ++; } else if (n instanceOf element) {elemento e1 = (elemento) n; // analizar recursivamente los elementos infantiles XML Parserelement (E1, Params, GlobalParams, SB); // Si el indicador de bucle no es verdadero, analice la siguiente etiqueta // Esto significa que debe analizar repetidamente la etiqueta de bucle, entonces no cambiaré, de lo contrario continuaré procesando el siguiente elemento boolean while_flag = maputils.getboolean (params, attrs.whall_flag, falso); if (! when_flag || }}} // ¿Qué debo hacer después del nodo de procesamiento del nodo? // Recicla el parámetro de alcance actual params.clear (); params = nulo; }} /** * Proceso de texto para reemplazar el parámetro #{elemento} * @param str * @param params * @return * @throws excepción * /private string handText (String str, map <string, object> params, map <string> globalParams) lanza excepción {// obtiene la variable string indexstr = maputils.getstring (params, attrs.whileLe_indexs); Integer index = null; if (stringUtils.isnotempty (indexstr)) {index = maputils.getInteger (params, indexstr); } // coincidir #{a} parámetro cadena reg1 = "( #// {) (// w+) (//})"; // coincide con el parámetro de $ {a} string reg2 = "(// $ // {) (// w+) (//})"; Patrón P1 = Pattern.compile (Reg1); Matcher M1 = P1.Matcher (STR); Patrón P2 = Pattern.compile (Reg2); Matcher M2 = P2.Matcher (STR); Cadena whileList = mapUtils.getString (params, attrs.whall_list); Map <string, object> allparams = getAllParams (params, globalParams); while (m1.find ()) {string tmpkey = m1.group (2); Clave de cadena = WHILELIST == NULL? TMPKEY: (WHILELIST+"_"+TMPKEY); clave = index == nulo? clave: (clave+índice); String rekey = "#{"+key+"}"; // Si está en un bucle similar a foreach, es posible que necesite reemplazar el parámetro #{xx} con #{xx_0}, #{xx_1} str = str.replace (m1.group (0), rekey); CurrParams.put (Key, AllParams.get (TMPKey)); } while (m2.find ()) {string tmpkey = m2.group (2); Valor de objeto = allparams.get (tmpkey); if (value! = null) {str = str.replace (m2.group (0), getValue (valor)); }} return str; } private String getValue (valor de objeto) {string result = ""; if (valor instanceof date) {SimpleDateFormat sdf = new SimpleDateFormat ("yyyyy-mm-dd hh: mm: ss"); resultado = sdf.format ((fecha) valor); } else {result = string.ValueOf (valor); } resultado de retorno; } MAP privado <String, Object> GetAllParams (map <string, object> CurrParams, map <string, object> globalParams) {map <string, object> allparams = new Hashmap <String, Object> (); Allparams.putall (GlobalParams); allparams.putall (CurrParams); devolver todos los paramentos; } // analizar un elemento xml private tempval parseroneElement (map <string, object> curvarams, map <string, object> globalParams, element ele, stringBuilder sb) lanza excepción {// Obtener la etiqueta XML Nombre String elename = ele.getName (); // ¿Continúa después de analizar un nodo? Si encuentra un nodo como si, debe determinar si la prueba está vacía. boolean iscontinue = false; // declarar un nodo de nodo abstracto nodo = nulo; if (stringUtils.isnotempty (elename)) {// Use la fábrica de nodo para obtener un objeto de nodo basado en el nombre del nodo, como si nodo o foreach nodo = nodefactory.create (elename); // Analice este nodo y devuelve si el contenido en el nodo aún debe analizarse IsContinue = node.parse (CurrParams, GlobalParams, ELE, SB); } return new Tempval (isContinue, ele, nodo); } public map <string, object> getParams () {return CurrParams; } / *** Encapsula el resultado después de que un elemento XML se analiza* @author rongdi* / final de clase estática Tempval {private boolean isContinue; elemento privado ele; Nodo Basenode privado; Tempval público (booleano iscontinue, elemento ele, nodo basenode) {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 (elemento ele) {this.ele = ele; } public basenode getNode () {return node; } public void setNode (nodo Basenode) {this.node = node; }}} importar org.dom4j.element; import java.util.hashmap; import java.util.map;/*** abstracto nodo* @author rongdi*/public abstract class Basenode {public abstract Boolean Parse (Map <String, Object> CurrParams, Map <String, Object> GlobalParams, Element ele, StringBuilder) Shows Excepción; 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, MAP <String, Object> GlobalParams) {Map <String, Object> AllParams = new Hashmap <String, Object> (); Allparams.putall (GlobalParams); allparams.putall (CurrParams); devolver todos los paramentos; }} import java.util.map; import ognl.ognl; import org.apache.commons.lang.stringutils; import org.dom4j.element;/*** if node* @author rongdi*/public class IfNode extiende Basenode {@Override public Public Pepril (Map <String, Object> Currparams, Map <String, Object, se extiende BASEnode {@Override Public Boolean Parse (MAP <String, Object> Currparams, Map <String, Object, se extiende Basenode, @Override Public Boolean Parse (Map <String, Object> Currparams, Map <String, Object, Object, Object, Object, Object, Object, Objectems, ELE, StringBuilder sb) lanza la excepción {// Obtener el atributo de prueba de if nodo string teststr = ele.attributeValue ("test"); prueba booleana = falso; Pruebe {if (StringUtils.ISNotEmpty (teststr)) {// fusione variables globales y variables locales map <string, object> allparams = getAllParams (CurrParams, globalParams); // use ognl para determinar la prueba verdadera o falsa = (boolean) ognl.getValue (teststr, allparams); }} catch (Exception e) {E.PrintStackTrace (); arrojar una nueva excepción ("Juez de parámetros de operación"+teststr+"ilegal"); } if (ele.content ()! = null && ele.content (). size () == 0) {test = true; } prueba de retorno; }} import java.util.arrayList; import java.util.hashmap; import java.util.list; import java.util.map; import java.util.set; import ognl.ognl; importar org.apache.commons.collections.maputils; org.dom4j.element;/** Los atributos del nodo foreach son los siguientes elementos de recolección que debe atravesar. El índice variable almacenado en cada elemento después de atravesar la colección. El número de índice de la colección es como 0, 1, 2 ... separador después de atravesar, empalmando con un separador especificado. Los símbolos que comienzan el empalme después del recorrido son los siguientes (cierre los símbolos que terminan el empalme después del traversal son los siguientes) */public class foreachNode extiende Basenode {@Override public boolean Parse (map <string, object> CurrParams, map <string, objeto> globalParams, elemento elemental ele, string sb) shows excepción {string string condyions, string condyions, CurrParams, map <string, objeto> globalParams, element ele, string sbuilder) shows {string condicion string {string condicion {string condicions, Colecciones de cadenatr = ele.attributeValue ("colección"); Cadena itemstr = ele.attributeValue ("item"); String index = ele.attributeValue ("índice"); String separatorstr = ele.attributeValue ("separador"); Cadena OpenStr = Ele.AttributeValue ("Open"); String Closestr = ELE.ATTRIBUDEVALUE ("Cerrar"); if (stringUtils.isEmpty (index)) {index = "index"; } if (stringUtils.isEmpty (separatorstr)) {separatorstr = ","; } if (StringUtils.ISNotEmpty (OpenStr)) {CurrParams.put (attrs.whall_open, openstr); } if (StringUtils.ISNotEmpty (Closestr)) {CurrParams.put (attrs.whall_close, cerrador); } if (stringUtils.isNotEmpty (collectionstr)) {curparams.put (attrs.whall_list, collectionStr); } CurrParams.put (attrs.whall_separator, separatorstr); if (index! = null) { /*** Si hay el valor de la variable de bucle actual en la variable local, significa que no es la primera vez que ha ingresado a la etiqueta de bucle. Elimine la etiqueta de inicio * y agregue 1 al valor variable local */ if (CurrParams.get (index)! = NULL) {CurrParams.remove (attrs.whall_start); CurrParams.put (index+"_", (integer) currparams.get (index+"_")+1); } else {// La primera vez que ingresa a la etiqueta de bucle curparams.put (attrs.whall_start, true); CurrParams.put (índice+"_", 0); } CurrParams.put (index, (integer) currparams.get (index+"_")); } condición booleana = true; MAP <String, Object> AllParams = GetAllParams (CurrParams, GlobalParams); Colección de objetos = nulo; if (stringUtils.isnotempty (collectionstr)) {// Obtener la colección para ser colección = ognl.getValue (colección, allparams); // Si la propiedad de la colección no está vacía, pero la condición es nula, se agrega una condición de límite de forma predeterminada si (StringUtils.isEmpty (condicionStr)) {// Aquí solo usaré una colección para demostrarla. También puede agregar una matriz, pero simplemente cambiarla a .length if (colección de instancia de lista) {condiciónstr = index+"_ <"+collectionstr+". Size ()"; } else if (colección instancia de map) {map map = (map) colección; Set set = map.entryset (); Lista list = new ArrayList (set); allparams.put ("_ list_", list); condiciónstr = index+"_ <_ List _"+". Size ()"; }}} CurrParams.remove (attrs.whall_end); if (StringUtils.ISNotEmpty (ConditionStr)) {// El valor de la condición de cálculo condición = (boolean) ognl.getValue (condicionStr, AllParams); Map <string, object> tempMap = new HashMap <> (); tempMap.putall (AllParams); tempMap.put (index+"_", (integer) curparams.get (index+"_")+1); CurrParams.put (attrs.whall_end ,! (boolean) ognl.getValue (condicionstr, tempMap)); } bandera booleana = true; CurrParams.put (attrs.whall_index, index); CurrParams.put (attrs.whall_flag, true); if (condición) {try {if (stringUtils.isnotempty (itemstr) && stringUtils.isNotEmpty (collectionstr)) {objeto valor = null; int idx = Integer.ParseInt (currparams.get (index+"_"). toString ()); if (colección de instancia de lista) {valor = ((list) colección) .get (idx); CurrParams.put (itemstr, valor); } else if (colección instancia de map) {map map = (map) colección; 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 ("Obtener valor de una colección o mapa"+CurrParams.get (index)+"Error"+E.getMessage ()); }} else {flag = false; DestroyVars (CurrParams, índice, itemstr); } Bandera de retorno; } / *** Si es la primera vez que ingresa a la etiqueta de bucle, deletree el contenido de Open* / @Override public void pre (map <string, object> CurrParams, map <string, object> globalParams, element ele, stringBuilder sb) lanza la excepción {super.pre (CurrPreams, globalparams, ele, sb); boolean start = maputils.getBoolean (CurrParams, attrs.whall_start, false); if (start) {String Open = MapUtils.getString (CurrParams, attrs.whall_open); sb.append (abierto); }} / *** Si la etiqueta de bucle finalmente se ingresa, el contenido de cierre se deletrea en el final* / @Override public void After (map <string, object> CurrParams, Map <String, Object> GlobalParams, Element ELE, StringBuilder sb) lanza la excepción {super.after (CurrParams, GlobalParams, ELE, SB); boolean end = maputils.getBoolean (CurrParams, attrs.whall_end, falso); String separator = maputils.getString (curvarams, attrs.whall_separator); if (! end && stringUtils.isnotempty (separator)) {sb.append (separador); } if (end) {String Close = MapUtils.getString (CurrParams, attrs.whall_close); if (sb.ToString (). endswith (separator)) {sb.deletecharat (sb.length () - 1); } sb.append (cierre); }} // libera la variable temporal privada void destrucyVars (map <string, object> CurrParams, String index, string varstr) {curparams.remove (attrs.while_index); CurrParams.remove (attrs.whall_flag); CurrParams.remove (attrs.whall_separator); CurrParams.remove (attrs.whall_start); CurrParams.remove (attrs.whall_end); CurrParams.remove (attrs.whall_list); }} importar org.dom4j.element; import java.util.map; public class sqlnode extiende Basenode {@Override public boolean Parse (map <string, object> curparams, map <string, object> globalParams, element ele, stringBuilder sb) Excepción {return triate; }} import java.util.arrays; import java.util.list; import java.util.map; import java.util.concurrent.concurrenthashmap;/*** nodo factory*/public class nodefactory {mapa estático privado <string, Basenode> nodemap = nuevo concurrenthmap <String, Basenode> (); Lista estática final privada <String> WhileList = arrays.aslist ("foreach"); static {nodemap.put ("if", new ifNode ()); nodemap.put ("sql", nuevo sqlnode ()); nodemap.put ("foreach", nuevo foreachNode ()); } public static boolean ishle (String ElementName) {return whileist.contains (elementName); } public static void addNode (string nodename, nodo basenode) {nodemap.put (nodo, nodo); } public static Basenode create (String NodeName) {return noDEMap.get (nodename); }}/*** Varias etiquetas* @author rongdi*/public class attrs {public final static string transaccional = "transaccional"; Cadena estática final pública while_start = "while-start"; Cadena estática final pública while_end = "while-end"; cadena estática final pública while_open = "while-open"; cadena estática final pública while_close = "while-close"; cadena estática final pública while_separator = "while-separator"; cadena estática final pública while_index = "while-index"; cadena estática final pública while_flag = "while-flag"; Cadena estática final pública while_list = "while-list"; Cadena estática final pública cuando_flag = "When-Flag"; Public static final String Process_var = "Process-Var"; Cadena estática final pública result_flag = "Result-Flag"; Public final static string return_flag = "return-flag"; Public final static string console_var = "console-var"; Cadena estática final pública do = "do"; Public final static string index = "índice"; Condición de cadena estática final pública = "condición"; Nombre de cadena estática final pública = "Nombre"; Public Final Static String Value = "Value"; public static final String type = "type"; Formato de cadena final estática pública = "formato"; Cadena final estática pública if = "if"; Cadena final estática pública más = "else"; Public final static string file = "archivo"; Fecha de cadena final estática pública = "fecha"; Cadena final estática pública ahora = "ahora"; Public estática final de cadena decimal = "decimal"; public static final String id = "id"; public static final String params = "params"; public static final String Target = "Target"; Public static final String single = "Single"; public static final String Paging = "Paging"; Public static final String desc = "Desc"; Public estática final final de cadena Break = "Break"; Public static final String Continir = "Continuar"; Public static final String Collection = "Collection"; Public static final String var = "var"; public static final String Executor = "Ejecutor-1"; public static final String Rollback_flag = "Rollback-Flag"; Public static final String Service = "Service"; Public static final String ref = "ref"; public static final String bizs = "bizs"; Public static final String títulos = "títulos"; columna de cadena final estática pública = "columnas"; public static final String Curruser = "Curruser"; Public static final String CurrPerm = "CurrPerm"; public static final String tarea_Executor = "Taskexecutor"; Public static final String delimiter = "delimitador"; Public static final String opername = "opername"; } CurrParams.remove (varstr); CurrParams.remove (índice); CurrParams.remove (índice+"_"); }}Adjunte el archivo 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.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0. http://maven.apache.org/maven-v4_0_0.xsd "> <modelVersion> 4.0.0 </modelVersion> <MoupRupid> com.rd </groupid> <artifactid> parser </artifactid> <compaCkaging> jar </packaging> <versión> 1.0-snapshot </ververser> <name> myParser </name> <Ull> http://maven.apache.org </sl> <pendencies> <pendency> <MoupRoD> DOM4J </Groupid> <AtifactId> DOM4J </ArtifactId> <PROPESPONSE> 1.6.1 </Version> </Dependency> <Spendency> <ProupId> OpenSymphony </GroupID> <AtifactId> <Versión> 2.6.11 </versión> </pendency> <epardency> <proupid> commons-colecciones </proupid> <artifactid> commons-colections </artifactid> <version> 3.2.1 </versión> </pendency> <pendency> <proupid> commons-lang </groupid> <artifiCiD> commons-lang </artifactid> <Versión> 2.6 </version> </Versión </versión> <Spendency> <ProupId> Junit </proupid> <artifactId> Junit </artifactid> <versión> 3.8.1 </versión> <cope> test </cope> </pendency> </dependency> </pendencs> <struye> <contresers> <consome> <consome> <sirectory> src/main/java </sorectory> <incluye>***/*. </INCENDIDOS> </RUNTCE> <CRUNTECE> <DIRECTORIO> SRC/MAIN/RESUROS </sirectory> <incluye> <incluido> **/*</cluido> </ recursos> </ recursos> </testResources> <prestresources> <testresource> <sirectory> $ {Project.basedir}/src/test/java </testresource> <Directory> $ {Project.Basedir}/src/test/recursos </sirectory> </testResource> </testResources> <glugins> <grupoid> org.apache.maven.plugins </groupid> <artifactid> maven-compiler-plugin </artifactid> <versions> 3.1 </versión> <figuration> <figuration> <outia> 1.8 Source> 1.8 Source> 1.8 Source> <Target> 1.8 </target> <coding> UTF-8 </coding> </figuration> </glugin> </glugins> </build> </proyecto>El método anterior para implementar MyBatis Dynamic SQL por usted mismo es todo el contenido que he compartido con usted. Espero que pueda darle una referencia y espero que pueda apoyar más a Wulin.com.