Después de trabajar duro durante varias noches para depurar el programa, escribir varios blogs y finalmente establecer el mecanismo de expansión para la configuración de MyBatis. Aunque el mecanismo de extensión es importante, al menos no es tan inspirador si no hay una función de extensión verdaderamente práctica. Este blog le dará algunos ejemplos de extensiones.
La razón de este estudio del código fuente es la compatibilidad entre las bases de datos Oracle y MySQL. Por ejemplo, el uso de líneas verticales dobles como conectores en Oracle, y usando la función Concat en MySQL; Por ejemplo, usando la función de decodificación en Oracle, mientras solo usa el caso estándar cuando está en MySQL; Por ejemplo, elimine la tabla de formulario donde el campo1 in (seleccione la tabla de formulario de campo1 donde el campo2 =?) Se puede ejecutar, pero se lanzarán excepciones en mysql, etc.
Comencemos resolviendo estos problemas de compatibilidad. Primero, debe agregar configuraciones relacionadas con la identidad de la base de datos a la configuración:
< name = "mapperLocations"> <Array> <Value> classpath*: **/*. sqlmapper.xml </value> </array> </propiety> <!-Configuración de identificación del producto de la base de datos-> <Property Name = "DatabaseIdProvider"> <Bean> <Propiedad Nombre = "Propiedades"> <Props> <! MySQL se usa como DatabaseId In Configuration. Las palabras clave de implementación nativa de MyBatis son sensibles a los estuches. No probé Oracle y DB2 -> <prop key = "mysql"> mysql </prop> <prop key = "oracle"> oracle </pr> <prop key = "h2"> h2 </pr> <proping key = "db2"> db2 </pp> </props> </ behor>
1. Problema de conector
1. Escribir la clase de implementación de la función de configuración SQL
clase pública ConcatsqlConfigFunction extiende AbstractSqlConfigFunction {// El nivel de orden predeterminado se establece en la clase matriz abstracta @OverridePublic String getName () {return "concat";} @overridePublic string string eval (string databaseId, string [] args) {si (args.length <2) {throwexception ("la función concat (la función concats requiere al alminar el concat argumentos. ");} if (" mySql ".equalSignorecase (databaseId)) {return" concat ("+tool.string.join (args,", ")+") ";} else {return tool.string.join (args," || ");}}}2. Regístrese en el bloque de código estático de la clase Schemahandlers, o llame al método Schemahandlers en la clase de inicialización de inicio.
static {// Registro de DeclarationHandlerRegister ("Cache-Ref", new CacherefStatementHandler ()); Registro ("Cache", nuevo CachestatementHandler ()); registro ("Parametermap", New ParametermStatementHandler (); Registro ("ResultMap", New ResultMapStatemementHandler (); SqlStatementHandler());register("select|insert|update|delete", new CRUDStatementHandler());//Register the default namespace ScriptHandlerregister("trim", new TrimScriptHandler());register("where", new WhereScriptHandler());register("set", new SetScriptHandler());register("foreach", new Foreachscripthandler ()); registrar ("if | when", new ifscripthandler ()); registrar ("elegir", new ElegesScripthandler ()); // registrar ("When", new ifscriptHandler ()); registrar ("Otro de lo contrario", new OtherWisesChandler ()); registrar ("Bind", new BindScriptHandler (); // DBStatementHandler (), new dbscripthandler ()); // registrar sqlconfigFunctionRegister (new DecodesqlConfigFunction ()); registrar (nuevo ConcatsqlConfigFunction ()); // Registro SqlConfunctionFactoryRegister (New LikeQlConfigFunctyFactory ();}Además de registrar ConcatsQLConfigFunction, el código anterior también tiene algunos otros códigos de registro, que se dan aquí y se omitirán a continuación.
3. Modifique la configuración de SQLMapper
<select id = "selectString" resultType = "String"> Seleccionar param_name, $ concat {param_code, param_name} as code_name desde bf_param_enum_def <if test = "null! = paramname y ''! = paramName"> donde param_neki como $ coScat {'%'%' {paramname, jdbctype}, vARChype}, var = VarHarchtype = VarHar} '%'} </if> </select>4. Escribir clase de interfaz
@RepositoryPublic Interface IEXAMPLEDAO {public String selectString (@param ("paramName") string paramName);}5. Escribir clases de prueba
@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (ubicaciones = {"classpath: spring/applicationContext.xml"})@componentPublic de clase EjempledaTaTest {@ResourcePrivate IExAMPLEDAO DAO; dao.selectstring ("show"); afirmar.assertEquals ("área de exhibición", a);}}6. Ejecute de la siguiente manera en MySQL y H2 respectivamente (ajuste el nivel de registro de MyBatis para rastrear)
(1) mysql
20161108 00: 12: 55,235 [main]-[debug] ==> Preparación: seleccionar param_name, concat (param_code, param_name) como code_name de bf_param_enum_def donde param_name me gusta concat ('%',?, '%') 20111108 00: 12: 55,269 [principal]-[debug] (Cadena) 20161108 00: 12: 55,287 [main]-[traza] <== columnas: param_name, code_name20161108 00: 12: 55,287 [main]-[traza] <== fila: área de visual(2) H2
20161108 00: 23: 08,348 [main]-[debug] ==> Preparación: seleccione param_name, param_code || param_name as code_name de bf_param_enum_def where param_name como '%' || 00: 23: 08,411 [Main]-[traza] <== columnas: param_name, code_name20161108 00: 23: 08,411 [main]-[traza] <== fila: área de visual
Como puede ver, se ha resuelto el problema de compatibilidad de los conectores.
Además, también descubrimos que la escritura es más problemática cuando se usa palabras clave similares, así que le damos un nuevo conjunto de funciones de configuración SQL:
Public Class LikeqlConfigFunctionFactory implementos iSQLConfigFunctTAfTory {@OverridePublic Collection <isqlconfigFunction> getSqlConfigFunctions () {returns.aslist (getLeftlikesqllInsqly getLikesqlconfigFunction ());} private isqlconfigFunction getLeftlikesqlconfigFunction () {return new AbstractLikesqlConfigFunction () {@overRidePublic String getName () {return "like";}@overridePublic string (string arg) {return "como" $ concat {'%', "+arg+"} ";}};} private isqlconfigFunction getRightLikesqlConfigFunction () {return new AbstractLikesqlConfigFunction () {@@overDepublic String getName getName () {return" rike ";}@overrideprotected String Eval (String Eval (String) {return" $ concat {"+arg+", '%'} ";}};} private isqlconfigFunction getLikesqlconfigFunction () {return new AbstractLikesqlConfigFunction () {@@overDepublic getName getName () {return" como ";}@Stringprotected String Eval (String) {Return $ concat {'%', "+arg+", '%'} ";}};} private abstract class abstractLikesqlConfigFunction extiende AbstractSqlConfigFunction {@OverridePublic String String Eval (String DatabaseId, String [] args) {si (args.length! = 1) {throLE eval (args [0]);} protegida abstract string eval (string arg);}}Aquí, se definen un conjunto de funciones de configuración SQL, con similitud izquierda, similitud correcta y coincidencia de similitud media, y las funciones de configuración SQL también pueden anidarse. Por lo tanto, el archivo de configuración de SQLMapper se simplifica a:
<select id = "selectString" resultType = "String"> Seleccionar param_name, $ concat {param_code, param_name} as code_name de bf_param_enum_def <if test = "null! = paramname and ''! = paramName"> where param_name $Los resultados de la ejecución son exactamente los mismos.
Si todavía lo encuentra problemático, porque param_name y paramname son correspondencias similares a camellos, incluso puede agregar una función en forma de campo y modificar la configuración a
Donde $ Field Liking {#{param_name, jdbctype = varchar}}Si se combina con el diccionario de datos, la configuración JDBCType también se puede generar automáticamente:
Donde $ Field Liking {#{param_name}}En este caso, si hay múltiples parámetros, no habrá ambigüedad (o una función de configuración recientemente definida $ me gusta {} se utilizará para eliminar la ambigüedad), por lo que se pueden simplificar múltiples condiciones para:
donde $ le gusta {#{param_name, param_name2, param_name3}}Por supuesto, hay más simplificaciones excavables que ya no están solo en el alcance de la compatibilidad, por lo que no iremos más allá aquí.
2. Función/caso de decodificación ... cuando
La función de decodificación en Oracle es muy conveniente, y la sintaxis es la siguiente:
Decodificación (condición, valor 1, valor de retorno 1, valor 2, valor de retorno 2, ... valor n, valor de retorno n [, valor predeterminado])
Escritura estándar de equivalentes:
Condición de caso cuando el valor 1 luego el valor de retorno 1 cuando el valor 2 y el valor de retorno 2 ... Cuando el valor n, entonces el valor de retorno n [más predeterminado] final
Ahora implementemos una función de configuración de $ decode:
La clase pública decodesqlconfigFunction extiende abstractSqlConfigFunction {@OverridePublic String getName () {return "decode";}@overridePublic string eval eval (string databaseId, string [] args) {if (args.length <3) {show.throwException ("La función de decodificación requiere al menos tres tres args argumentos. ");} if (" h2 ".equalSignorecase (databaseId)) {// Al probar, use H2 en lugar de Oracle, y modifíquelo a Oraclereturn en el programa oficial" Decode ("+Tool.String.JoN (JOIN (", ")+") ";} el otro {StringBuffer SB = New StringBuffer (); SB.Append (" Case ("" "" ") .Append (args [0]); int i = 2, l = args.length; for (; i <l; i = i+2) {sb.append (" when ") .append (args [i-1]). append (" entonces ") .append (args [i]);} si (i == l) {// cuando finaliza el ciclo, los dos son iguales a los últimos parámetros que se utilizan los últimos parámetros que utilizan el último parámetro que se utilizan el último parámetro. sb.append ("else") .append (args [l-1]);} sb.append ("end"); return sb.ToString ();}}}Luego use Schemahandlers para registrarse y modificar la configuración en SQLMapper:
<select id = "selectString" resultType = "String"> Seleccionar param_name, $ decode {#{paramName}, '1', 'a', '2', 'b', 'c'} como decode_test desde bf_param_enum_def <if test = "null! = paramname y '! = paramname"> where param_name $ { {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{» jdbctype = varchar}} </if> </select>Las pruebas son las siguientes:
(1) en H2 (reemplace Oracle con H2)
20161108 06: 53: 29,747 [Main]-[Debug] ==> Preparación: Seleccionar param_name, decode (?, '1', 'a', '2', 'b', 'c') como decode_test de bf_param_enum_def donde param_name como '%' ||
(2) En mysql
20161108 06: 50: 55,998 [principal]-[debug] ==> Preparación: seleccionar param_name, ¿caso? Cuando '1' entonces 'A' When '2' entonces 'B' Else 'C' finaliza como decode_test de bf_param_enum_def donde param_name me gusta '%' ||? || '%'
Lo anterior es una introducción detallada a la extensión y aplicación de la configuración de SQLMapper en MyBatis presentada por el editor (1). Espero que te sea útil. Si tiene alguna pregunta, déjame un mensaje y el editor le responderá a tiempo. ¡Muchas gracias por su apoyo al sitio web de Wulin.com!