如何解析Mybatis xml文件中配置的sql

严成礼
2023-12-01

首先抽象一个SQL语句类:

public abstract class AbstractSQLStatementNode implements ISQLStatement {

	protected List<ISQLStatement> sqlStatements = new ArrayList<>();
	
	@Override
	public void appendSQL(ISQLStatement sql) {
		sqlStatements.add(sql);
	}


	@Override
	public String getSQL(Object object) {
		StringBuilder sb = new StringBuilder();
		for (ISQLStatement stmt : sqlStatements) {
			sb.append(stmt.getSQL(object));
		}
		return sb.toString().trim();
	}

}

然后是文本SQL:

public class PlainSQLNode extends AbstractSQLStatementNode  {

	private final String sql;

	public PlainSQLNode(String sql) {
		this.sql = sql;
	}

	@Override
	public String getSQL(Object object) {
		return sql;
	}

	@Override
	public String toString() {
		return sql;
	}

}


以Mybatis xml中<if test="...">...</if>为例

public class IfSQLNode extends AbstractSQLStatementNode {

	private final String test;
	
	public IfSQLNode(String test) {
		this.test = test;
	}

	public String getTest() {
		return test;
	}

	@Override
	public String getSQL(Object object) {
		try {
			Boolean b = (Boolean) Ognl.getValue(test, object, Boolean.TYPE);
			return b ? super.getSQL(object) : "";
		}
		catch (OgnlException e) {
			 throw new SQLSyntaxException(e);
		}
	}

}

再增加一个Include标签例

public class IncludeSQLNode extends AbstractSQLStatementNode {

	private final TableNode node;
	private final String refid;
	
	public IncludeSQLNode(TableNode node, String refid) {
		this.node = node;
		this.refid = refid;
	}
	
	@Override
	public String getSQL(Object object) {
		SQLNode sqlnode = node.getSQLNode(refid);
		return sqlnode.getSQL(object);
	}

}


其它的xml标签类似,完成最终的sql

调用AbstractSQLStatementNode.getSQL方法,参数为客户端传入参数

XML例子如下:

	<select id="findPage" parameterType="java.util.Map" resultMap="ORG">
 		SELECT * FROM XT_ORG WHERE  BDELETE<>1  <if test="name != null"> AND NAME=#{name}</if> LIMIT #{OFFSET}, #{ROWS}
 	</select>


根据是否传入了name,即可成功执行出最终的sql

 SELECT * FROM XT_ORG WHERE  BDELETE<>1 AND NAME=#{name} LIMIT #{OFFSET}, #{ROWS}

再解析SQL得到,并提出参数

 SELECT * FROM XT_ORG WHERE  BDELETE<>1 AND NAME=? LIMIT ?,?

即可生成最终的PrepareStatement

 类似资料: