環境:Windows 7 + iBatis 2.3.0.677 + OSCache 2.4.1。配置磁盤緩存時,查詢執行第二次拋出 java.io.FileNotFoundException: 文件名、目錄名或卷標語法不正確。
<cacheModel type="OSCACHE" id="productCache">
<flushOnExecute statement="Product.insert"/>
<flushOnExecute statement="Product.delete"/>
</cacheModel>
<select id="getById" cacheModel="productCache" parameterClass="int" resultClass="Product">
select id, name, description as desc1 from test_product where id = #value#
</select>
cache.memory=false
cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
cache.path=e:\\OSCache\\cache
cache.algorithm=com.opensymphony.oscache.base.algorithm.LRUCache
Unable to write 'e:\OSCache\cache\application\1991729862|2162672802|5|Product_31getById|62996507|_49_50_51...|executeQueryForObject.cache'
Exception: java.io.FileNotFoundException, Message: 文件名、目錄名或卷標語法不正確
iBatis 生成的緩存 Key 由 CacheKey.toString() 產生,格式為:
hashcode|checksum|param1|param2|...|sql語句
其中包含大量 豎線符號 `|`。Windows 檔案系統禁止檔名包含 `|`,Linux 則允許,導致跨平台不相容。
修改 com.ibatis.sqlmap.engine.cache.CacheKey.toString(),將 `|` 替換為合法字元(如 `-`):
public String toString() {
StringBuffer buf = new StringBuffer().append(hashcode).append('|').append(checksum);
for (int i = 0; i < paramList.size(); i++) {
buf.append('|').append(paramList.get(i));
}
return buf.toString().replace('|', '-'); // 關鍵修復
}
編譯後將 CacheKey.class 替換至 iBatis JAR 或專案 classes 目錄(優先載入)。
CacheKey,若啟用檔案持久化同樣會遇到此問題。toString() 縮短邏輯。CacheKey.equals() 邏輯決定緩存命中規則,需確保參數順序、類型一致性。