動態組裝SQL是實際應用中的一個常見問題,我發現在很多論壇中的解決方案都不干淨,下面是我在很多項目中使用的方案,簡洁有效.
基本概念如下:
1. 使用模板技術,如Velocity,FreeMarker;
2. 在SQL中不要使用?,使用自己的place holder ,such as #{variableName};
象下面的SQL語句
select firstName
,lastName
from users u
where u.userId= #{userId}
#if($companyId)
and u.companyId=#{companyId}
#end
處理過程如下:
1.將所有變量放進一個MAP中;
2.用VELOCITY進行MERGE,將得到以下的SQL,假定companyId 不為空;
select firstName
,lastName
from users u
where u.userId= #{userId}
and u.companyId=#{companyId}
3.再將上面的SQL進一步處理,根據SQL語句中的placeHolder順序和MAP中的變量,生成一個變量的LIST,同時將變量的placeHolder轉換成?;
4.將變量LIST的數值依次注入到preparedStatement中;
Tips:
這里還可生成一個完全可執行的
SQL
語句輸出到
LOG
中
,
以便進行除錯;
5.執行SQL, 用reflection技術將ResultSet轉換成voList;
將上面的過程封裝成一個
Class ,
只需將
sqlName,parameterMap,voClass
傳入便可返回一個
voList
或數組
.
此舉將大大減化
DAO
的代碼
,
根據我的經驗
,
代碼最起碼減少
70%,
更為重要的是查詢非常容易維護
,
極大地減少了出錯的概率
,SQL
語句清晰易懂
,
不再是醜陋的
criteria,
也不再是將一個個的分散的
SQL
片斷
,
我們的程序員將會有更多的時間來寫
SQL,
而不是做其它讓人厭煩的工作
,
排錯也變得异常簡單
,
唯一可能出錯的地方只能在
SQL
上
,
只要將
LOG
輸出的完整可執行
SQL
放在
database client
中執行一下
,
問題在哪兒
,
一目了然
.
我相信此方法
比起
iBatis, Spring
的
jdbcTemplate,Hibernate
的
Criteria
要容易使用得多
.
其實
Hibernate
的
HQL,
也可以用此方法來動態生成
HQL.