Java开发人员可能会碰到的最棘手的事情之一就是在Java代码中嵌入SQL语句。通常情况下,这是因为需要动态生成SQL语句 - 否则可以将其外部化到文件或存储过程中。正如你已经了解到的,MyBatis在其XML映射功能中有一个强大的解决方案来生成动态SQL。然而,有时候在Java代码中构建SQL语句字符串是必要的。在这种情况下,MyBatis还有一个特性可以帮助您,避免陷入典型的加号、引号、换行、格式化问题和嵌套条件语句处理额外逗号或AND连接符的混乱中。实际上,在Java中动态生成SQL代码可能会成为一场真正的噩梦。例如:
String sql = "SELECT P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME, "
"P.LAST_NAME,P.CREATED_ON, P.UPDATED_ON " +
"FROM PERSON P, ACCOUNT A " +
"INNER JOIN DEPARTMENT D on D.ID = P.DEPARTMENT_ID " +
"INNER JOIN COMPANY C on D.COMPANY_ID = C.ID " +
"WHERE (P.ID = A.ID AND P.FIRST_NAME like ?) " +
"OR (P.LAST_NAME like ?) " +
"GROUP BY P.ID " +
"HAVING (P.LAST_NAME like ?) " +
"OR (P.FIRST_NAME like ?) " +
"ORDER BY P.ID, P.FULL_NAME";
MyBatis 3提供了一个便利的工具类来帮助解决这个问题。通过使用SQL类,您只需创建一个实例,然后可以调用其方法逐步构建SQL语句。重写上面的示例问题时,可以使用SQL类来实现如下:
private String selectPersonSql() {
return new SQL() {{
SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME");
SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON");
FROM("PERSON P");
FROM("ACCOUNT A");
INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID");
INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID");
WHERE("P.ID = A.ID");
WHERE("P.FIRST_NAME like ?");
OR();
WHERE("P.LAST_NAME like ?");
GROUP_BY("P.ID");
HAVING("P.LAST_NAME like ?");
OR();
HAVING("P.FIRST_NAME like ?");
ORDER_BY("P.ID");
ORDER_BY("P.FULL_NAME");
}}.toString();
}
这个示例有什么特别之处?嗯,如果你仔细看的话,它不必担心意外重复出现“AND”关键字,也不需要在“WHERE”和“AND”之间进行选择或者两者都不需要。SQL类会处理好理解何时需要插入“WHERE”,何时使用“AND”以及所有的字符串拼接工作。