JFinal教程JfinalUIB 代碼筆記 (4)--- 高仿mybatis的sql的集中管理

實現sql的集中管理,簡單的把一些固定長度的sql移植進xml很簡單,這沒有什麼好多說的,關鍵問題是咱們平時處理的sql,有大量是動態長度的,好比說最多見的就是多條件的分頁查詢,每每咱們會在代碼中寫大量的if else,想把這些移植進xml就比較困難了,徹底仿製ibatis來作xml標籤工做量太大,最省事的處理方法就是能不能直接把Java代碼的邏輯處理方式移植進xml,而後對邏輯代碼進行解析,繞開那一大堆的xml標籤訂義,下面就是jfinaluib中的處理方式:java

1.0 暫時仍是用的拼接,沒有預處理,難點就是否是作到解析sql中表字段的類型對應的Java數據類型git

<?xml version="1.0" encoding="UTF-8"?>
<sql-statement namespace="pingtai.user"> 
<!-- 動態SQL處理 -->
<sql id="splitPage">
  <![CDATA[ 
         from pt_user u 
   left join pt_userinfo ui on u.userinfoids = ui.ids 
   left join pt_department d on u.departmentids = d.ids 
   where 1=1 
   <% if(!isEmpty(userClass)){ %>
     and u.userClass = '#userClass#'
   <% } %>
   
   <% if(!isEmpty(userName)){ %>
     and u.userName like '%#userName#%'
   <% } %>
   
   <% if(!isEmpty(names)){ %>
     and ui.names like '%#names#%'
   <% } %>
     ]]>
</sql>
</sql-statement>

下面是調用xml中sql進行解析的方法,語法解析是用的beetl模板進行的,固然你能夠換成freemark或者velocity也行,語法按他們的來就行sql

    /**
     * 獲取SQL,動態SQL
     * @param sqlId
     * @param param
     * @return
     */
    public static String getSql(String sqlId, Map<String, Object> param) {
     String sqlTemplete = sqlMap.get(sqlId);
     if(null == sqlTemplete || sqlTemplete.isEmpty()){
   log.error("sql語句不存在:sql id是" + sqlId);
     }
     String sql = BeetlKit.render(sqlTemplete, param);
  
  Set<String> keySet = param.keySet();
  for (String key : keySet) {
   String value = (String) param.get(key);
     sql = sql.replace("#" + key + "#", value);
  }
  
        return sql.trim();
    }

下面是調用方式測試

 Map<String, Object> param = new HashMap<String, Object>();
  param.put("userClass", "0");
  param.put("userName", "huajian");
  String sql = ToolSqlXml.getSql("pingtai.user.splitPage", param);

輸出sql:ui

from pt_user u
   left join pt_userinfo ui on u.userinfoids = ui.ids
   left join pt_department d on u.departmentids = d.ids
   where 1=1 and u.userClass = '0' and u.userName like '%huajian%'spa

這裏存在sql注入的問題:只能用不友好的處理方式來處理,字符串的驗證和過濾了,能夠查看ToolSqlXml中的stringVali方法.net

2.0 正在測試中的方法,因爲很可貴到sql中字典的數據類型,因此作預處理存在難度,可是下面的方法幾乎已經驗證是可行的,能作到預處理方法,code

此方法存在惟一不足的是對整形的處理,直接用的拼接,而後字符串使用預處理,不用擔憂存在sql注入,由於中間對整形的數據值作了數據類型轉換的測試,orm

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.beetl.core.BeetlKit;
public class Sql {
 public static void main(String[] args) {
  
  String sqlTemplete = "from pt_user u left join pt_userinfo ui on u.userinfoids = ui.ids left join pt_department d on u.departmentids = d.ids " +
  " where 1=1 " +
  "<% if(!isEmpty(userClass)){ %>"+
  "  and u.userClass = #'$userClass$'# "+
  "<% } %>"+
  
  "<% if(!isEmpty(userName)){ %>"+
  "  and u.userName like #'%$userName$%'# "+
  "<% } %>"+
  
  "<% if(!isEmpty(names)){ %>"+
  "  and ui.names like #'%$names$%'# "+
  "<% } %>"+ 
  
  "<% if(!isEmpty(status)){ %>"+
  "  and ui.status = #$status$# "+
  "<% } %>";
  Map<String, Object> paramMap = new HashMap<String, Object>();
  paramMap.put("userClass", "0");
  paramMap.put("userName", "aa");
  paramMap.put("names", "bb");
  paramMap.put("status", "1");
  
  String sql = BeetlKit.render(sqlTemplete, paramMap);
  
  Pattern pattern = Pattern.compile("#[\\w\\d\\$\\'\\%\\_]+#"); //#[\\w\\d]+#    \\$
  Pattern pattern2 = Pattern.compile("\\$[\\w\\d\\_]+\\$"); //#[\\w\\d]+#    \\$
  
  Matcher matcher = pattern.matcher(sql);
  
  List<String> listPram = new LinkedList<>();
  
  while (matcher.find()) {
   String clounm = matcher.group(0); // #'%$names$%'#
   
   Matcher matcher2 = pattern2.matcher(clounm);
   matcher2.find();
   String clounm2 = matcher2.group(0); // $names$
   
   if(clounm.equals("#"+clounm2+"#")){//整形
    String clounm3 = clounm2.replace("$", "");
    try {
     String val = (String) paramMap.get(clounm3);
     Integer.parseInt(val);
     sql = sql.replace(clounm, val);
     //listPram.add(val);
    } catch (NumberFormatException e) {
     throw new RuntimeException("查詢參數值異常");
    }
   }else{//字符串
    String clounm3 = clounm2.replace("$", "");
    String val = (String) paramMap.get(clounm3);
    
    String clounm4 = clounm.replace("#", "").replace("'", "").replace(clounm2, val);
    listPram.add(clounm4);
    
    sql = sql.replace(clounm, "?");
   }
  }
  
  System.out.println("預處理sql:" + sql);
  
  for (String param : listPram) {
   System.out.println("預處理sql參數:" + param);
  }
 }
}

最後輸出的結果是:xml

預處理sql:from pt_user u left join pt_userinfo ui on u.userinfoids = ui.ids left join pt_department d on u.departmentids = d.ids  where 1=1   and u.userClass = ?   and u.userName like ?   and ui.names like ?   and ui.status = 1
預處理sql參數:0
預處理sql參數:%aa%
預處理sql參數:%bb%

此方法存在的不足就是對整形的數據沒作預處理,就是ui.status = 1,可是經過#$status$#能肯定他是整形,殊不知道究竟是int、long、bigdecimal

userClass是char

userName是varchar

names是varchar

JfinalUIB中的實現類 ToolSqlXml.java

相關文章
相關標籤/搜索