实现Ibatis的动态解析SQL功能

17 篇文章 0 订阅
5 篇文章 0 订阅
曾几何时,一直想实现Ibatis的动态解析SQL功能,前些日子写了一个,基本实现(
[color=red]暂不支持嵌套标签[/color]):

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
*
* @description SQL动态解析
* @author 杨惠
* @version 1.0
* @date 2013-5-10
*/
public class SqlParse {

private static Logger logger = Logger.getLogger(SqlParse.class);
private String encoding = "UTF-8";
private SAXReader saxReader = null;
private Document document = null;
// XML文件全路径
private String filePath = "D:\\sql.xml";

public SqlParse() {
Init();
}

public SqlParse(String filePath) {
this.filePath = filePath;
Init();
}

/**
* 初始化
*/
private void Init() {
File file = new File(filePath);
if (file.exists() && file.isFile()) {
try {
saxReader = new SAXReader();
document = saxReader.read(file);
} catch (Exception e) {
logger.error(e);
document = null;
} finally {
saxReader = null;
file = null;
}
} else {
logger.error("指定文件不存在;");
}
}

/**
* 根据传入参数Map,动态替换SQL标签,解析成最终执行的SQL语句
*
* @param selectID
* select元素的ID
* @param mapPara
* SQL参数
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public final Map<String, String> parseSql(String strID,
Map<String, String> mapPara) throws Exception {
// 1.根据sqlID获得SQL语句元素
Element elementParent = (Element) document
.selectSingleNode("//select[@id='" + strID + "'] ");
if (elementParent == null) {
logger.info("文件名:" + filePath + ";信息:无id="
+ strID + "的元素。");
return null;
}
if (mapPara == null) {
mapPara = new HashMap<String, String>();
}
// 2.解析每一个子元素标签,例如isNotEmpty,isEqual等
List<Element> listElements = elementParent.elements();
if (listElements != null && (!listElements.isEmpty())) {
for (Element element : listElements) {
parseElement(element, mapPara);
}
}
// 3.解析SQL,用Map值替换SQL标签
String strSQL = elementParent.getStringValue();
Set<String> setKey = mapPara.keySet();
String strProperty = null;
for (Iterator<String> iterator = setKey.iterator(); iterator.hasNext();) {
strProperty = (String) iterator.next();
strSQL = strSQL.replaceAll("#" + strProperty + "#",
mapPara.get(strProperty));
strProperty = null;
}
Map<String, String> mapSQL = new HashMap<String, String>();
mapSQL.put("sqlText", strSQL.replaceAll("\\s{2,}", " "));
List<Attribute> listAttribute = elementParent.attributes();
for (Attribute attribute : listAttribute) {
mapSQL.put(attribute.getName(), attribute.getText());
}
// 4.释放变量
strID = null;
mapPara = null;
elementParent = null;
listElements = null;
setKey = null;
strSQL = null;
return mapSQL;
}

/**
* 解析每一个标签元素
*
* @param element
* 标签元素
* @param mapPara
* SQL参数
* @throws Exception
*/
private final void parseElement(Element element, Map<String, String> mapPara)
throws Exception {
// 获得节点名称、属性,属性值
String strElementName = element.getName();
String strProperty = element.attributeValue("property").trim();
String strPropertyValue = mapPara.get(strProperty);
// 是否删除该节点
boolean booDelete = false;
// 标签处理
if (StringUtils.equals(strElementName, "isNotEmpty")) {
// 是否非空
if (StringUtils.isBlank(strPropertyValue)) {
booDelete = true;
}
} else if (StringUtils.equals(strElementName, "isEmpty")) {
// 是否为空
if (StringUtils.isNotBlank(strPropertyValue)) {
booDelete = true;
}
} else {
// 比较值
if (StringUtils.isBlank(strPropertyValue)) {
booDelete = true;
} else {
double douPropertyValue = Double.parseDouble(strPropertyValue);
double douCompareValue = Double.parseDouble(element
.attributeValue("compareValue").trim());
if (StringUtils.equals(strElementName, "isGreaterThan")) {
// 是否大于
if (douPropertyValue <= douCompareValue) {
booDelete = true;
}
} else if (StringUtils.equals(strElementName, "isGreaterEqual")) {
// 是否大于等于
if (douPropertyValue < douCompareValue) {
booDelete = true;
}
} else if (StringUtils.equals(strElementName, "isLessThan")) {
// 是否小于
if (douPropertyValue >= douCompareValue) {
booDelete = true;
}
} else if (StringUtils.equals(strElementName, "isEqual")) {
// 是否等于
if (douPropertyValue != douCompareValue) {
booDelete = true;
}
} else if (StringUtils.equals(strElementName, "isNotEqual")) {
// 是否不等于
if (douPropertyValue == douCompareValue) {
booDelete = true;
}
} else if (StringUtils.equals(strElementName, "isLessEqual")) {
// 是否小于等于
if (douPropertyValue > douCompareValue) {
booDelete = true;
}
}
}
}
if (booDelete == true) {
element.getParent().remove(element);
}
// 释放变量
element = null;
mapPara = null;
strElementName = null;
strProperty = null;
strPropertyValue = null;
}

/**
* 获得:XML文件编码
*
* @return the encoding
*/

public final String getEncoding() {
return encoding;
}

/**
* 设置:XML文件编码
*
* @param encoding
* the encoding to set
*/

public final void setEncoding(String encoding) {
if (encoding != null) {
this.encoding = encoding;
}
}

/**
* 获得:Document
*
* @return the document
*/

public final Document getDocument() {
return document;
}

/**
* 设置:Document
*
* @param document
* the document to set
*/

public final void setDocument(Document document) {
if (document != null) {
this.document = document;
}
}

/**
* 获得:XMl文件全路径(含文件名)
*
* @return the filePath
*/

public final String getFilePath() {
return filePath;
}

/**
* 设置:XMl文件全路径(含文件名)
*
* @param filePath
* the filePath to set
*/

public final void setFilePath(String filePath) {
if (filePath != null) {
this.filePath = filePath;
}
}

public static void main(String[] args) {
try {
Map<String, String> mapPara = new HashMap<String, String>();
mapPara.put("menucode", "sysAdmin");
SqlParse sqlParse = new SqlParse("d:/sql.xml");
System.out.println(sqlParse.parseSql(
"queryMenuAsList", mapPara));
} catch (Exception e) {
e.printStackTrace();
}
}
}


上面main方法打印结果:
{id=queryMenuAsList, name=菜单表, sqlText= select menucode as 菜单编码,menuname as 菜单名称 from tb_upc_menu where 1=1 and menucode='myWork' }


Sql.xml:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<select id="queryMenuAsList" name="菜单表">
select menucode as 菜单编码,menuname as 菜单名称 from tb_upc_menu
where 1=1
<isNotEmpty property="menucode">
and menucode='myWork'
</isNotEmpty>
</select>
<select id="queryUserAsList" name="用户表">
select row_number() OVER(
order by createtime desc) as 序号,usercode as ID,username as 名称,mobile
as 手机号 from tb_upc_user
</select>
</root>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值