為了将一個不知道什麼類型的java對象存到資料庫裡面,用了個很惡心的方法:将對象序列化之後,儲存到資料庫的blob對象。這樣整個序列化和反序列化過程,都期望在ibatis中完成,上層就能直接擷取到需要的對象了。
第一次安裝網上的方式,想直接參考spring的blobbytearraytypehandler,将blob對象儲存到資料庫。因為這個類是需要的是byte數組,還不滿足我的需求,就參照這個類,繼承了abstractlobtypehandler,重寫getresultinternal和setparameterinternal。然後将這個type handler配置到ibatis的sqlmap檔案中。一切看上去很順利,結果啟動的時候ibatis報classcastexception,說這個handler無法強制轉換成typehandlercallback。
這個異常看上去很奇怪,去網上搜尋了inlineparametermapparser類,裡面的邏輯大緻是:
[cce lang=”java”]
} else if (“handler”.equals(field)) {
try {
value = typehandlerfactory.resolvealias(value);
object impl = resources.instantiate(value);
if (impl instanceof typehandlercallback) {
mapping.settypehandler(new customtypehandler((typehandlercallback) impl));
} else if (impl instanceof typehandler) {
mapping.settypehandler((typehandler) impl);
} else {
throw new sqlmapexception (“the class ” + value + ” is not a valid implementation of typehandler or typehandlercallback”);
}
} catch (exception e) {
throw new sqlmapexception(“error loading class specified by handler field in ” + token + “. cause: ” + e, e);
[/cce]
也就是說,如果在sql中配置的handler是同時相容typehandlercallback和typehandler接口的,spring的abstractlobtypehandler類,實作的是basetypehandler,應該沒有問題的啊。
反編譯了應用中試用的ibatis(版本是2.1.6),發現裡面的邏輯完全不一樣:
mapping.settypehandler(new customtypehandler((typehandlercallback)resources.classforname(value).newinstance()));
throw new sqlmapexception(“unrecognized parameter mapping field: ‘” + field + “‘ in ” + token);
這個古董是直接初始化之後強轉為typehandlercallback的。沒辦法,隻能自己實作這個接口。
public class javaserializeblobhandler implements typehandlercallback {
/*
* (non-javadoc)
* @see com.ibatis.sqlmap.engine.type.typehandler#valueof(java.lang.string)
*/
public object valueof(string s) {
return s;
* @see
* com.ibatis.sqlmap.client.extensions.typehandlercallback#getresult(com.ibatis.sqlmap.client.extensions.resultgetter
* )
public object getresult(resultgetter paramresultgetter) throws sqlexception {
byte[] buf = paramresultgetter.getbytes();
if(buf == null) {
return null;
objectinputstream inputstream = new objectinputstream(new bytearrayinputstream(buf));
return inputstream.readobject();
} catch (ioexception e) {
throw new illegalargumentexception(e);
} catch (classnotfoundexception e) {
* @see com.ibatis.sqlmap.client.extensions.typehandlercallback#setparameter(com.ibatis.sqlmap.client.extensions.
* parametersetter, java.lang.object)
public void setparameter(parametersetter paramparametersetter, object paramobject) throws sqlexception {
if (paramobject == null) {
paramparametersetter.setnull(types.blob);
bytearrayoutputstream bytestream = new bytearrayoutputstream();
objectoutputstream objectoutputstream = new objectoutputstream(bytestream);
objectoutputstream.writeobject(paramobject);
paramparametersetter.setbytes(bytestream.tobytearray());
不過接口中的valueof方法,到底是幹什麼用的,什麼時候調用的還沒搞清楚。将這個類配置在sqlmap的resultmap或sql中内聯,都能夠正常的對對象進行存取。
轉載自:https://coolex.info/blog/330.html