我發現了一個TypeHandler的bug你怎么看
<typeHandler?handler="com.user.type.UserTypeHandler"?javaType="com.user.model.User"/>?
<typeHandler?handler="com.user.type.SchoolTypeHandler"?javaType="com.user.model.School"/>
<select?id="selectUser"?resultMap="selectOneResult"?parameterType="user">
????select?*?from?user?where?id?=?#{id}?and?school=#{school,typeHandler=com.user.type.SchoolTypeHandler}
</select>
這樣運行時會先調用UserTypeHandler然后調用SchoolTypeHandler
UserTypeHandler調用沒有問題,但是SchoolTypeHandler調用時會發現傳入的parameterObject是User而不是School。。。。你怎么看?
2014-12-17
但如果是你來設計typeHandler的解析過程,它首先是要對你的User參數進行類型轉換的,轉換后肯定不再是User了(要不然你也不會進行類型轉換了),這個時候你又如何用#{school}來和轉換后的類型進行匹配呢,你可能會說,當我用typeHandler=com.user.type.SchoolTypeHandler的時候它就不應該再做類型轉換而把原來的類型給我,可這樣另一處#{id}應該是用轉換后的類型,那這樣經過UserTypeHandler后,竟然還需要同時保持轉換前與轉換后兩種類型,如果是你你會這樣設計嗎?不敢說mybaits的方式是perfect,但你該如何設計才能即達到你說的局部配置覆蓋全局的效果,又能不讓typeHandler的效果讓人感到歧義?不管討論的結果如何,我個人很贊賞你這種鉆研的精神和清晰的分析思路,用不了多久你就不用在這里和我討論了。:)
2014-12-12
我明白你的代碼結構與邏輯了,不能說是他邏輯上有問題,只能說你的代碼結構導致了這樣互相干擾的情況
你的類型轉換器的javaType與parameterType是同一個,這是問題的根源
你應該知道,無論是parameterType還是#{}中,只要出現java類型與類型轉換器中指定的javaType相同就會自動調用,這樣問題就來了,你的參數是User,他會自動調用UserTypeHandler中的setParameter方法來為SQL語句中所有的#{}賦值,一切要注意,我這說的是為“所有”的#{}賦值,當然,這個時候setParameter的參數parameter是User,從這個時候開始已經和你想的不一樣了,你用typeHandler=com.user.type.SchoolTypeHandler來改變了其中一個#{}的類型轉換器,但是沒用,你只是改變了類型轉換器,但參數是經過了UserTypeHandler傳給你的,所以是User,所以這個時候無所謂你寫的是#{school,typeHandler=com.user.type.SchoolTypeHandler}也好,還是寫成#{adsfdsafafdsdsaffdsafdsafdsafdsa,typeHandler=com.user.type.SchoolTypeHandler}也好,這已經不重要了,他們拿到的類型都是UserTypeHandler拿到的類型,為這些#{}賦值的控制,已經和你想的不一樣了。
2014-12-11
我需要看下user的類結構
2016-09-01
我也碰到相同的問題,User的所有屬性都用UserTypeHandler去處理,請問樓主最后怎么解決的
2014-12-11
我已經查過了mybatis的源碼,他確實是邏輯上有問題
public?void?setParameters(PreparedStatement?ps)?throws?SQLException?{ ????ErrorContext.instance().activity("setting?parameters").object(mappedStatement.getParameterMap().getId()); ????List<ParameterMapping>?parameterMappings?=?boundSql.getParameterMappings(); ????if?(parameterMappings?!=?null)?{ ??????for?(int?i?=?0;?i?<?parameterMappings.size();?i++)?{ ????????ParameterMapping?parameterMapping?=?parameterMappings.get(i); ????????if?(parameterMapping.getMode()?!=?ParameterMode.OUT)?{ ??????????Object?value; ??????????String?propertyName?=?parameterMapping.getProperty(); ??????????if?(boundSql.hasAdditionalParameter(propertyName))?{?//?issue?#448?ask?first?for?additional?params ????????????value?=?boundSql.getAdditionalParameter(propertyName); ??????????}?else?if?(parameterObject?==?null)?{ ????????????value?=?null; ??????????}?else?if?(typeHandlerRegistry.hasTypeHandler(parameterObject.getClass()))?{//如果根據parameterObject可以找到轉換器,那么value就賦值為parameterObject了 ????????????value?=?parameterObject; ??????????}?else?{ ????????????MetaObject?metaObject?=?configuration.newMetaObject(parameterObject); ????????????value?=?metaObject.getValue(propertyName); ??????????} ??????????TypeHandler?typeHandler?=?parameterMapping.getTypeHandler();//這兒獲得的轉換器是school的轉換器 ??????????JdbcType?jdbcType?=?parameterMapping.getJdbcType(); ??????????if?(value?==?null?&&?jdbcType?==?null)?jdbcType?=?configuration.getJdbcTypeForNull(); ??????????typeHandler.setParameter(ps,?i?+?1,?value,?jdbcType);//轉換器是school的?但是傳值是User ????????} ??????} ????} ??}2014-12-11
public?class?User?{ private?long?id?; private?String?name; private?String?password; private?String?sex; private?String?email; private?String?tel; private?String?department_name; private?String?department_id; private?School?school; ....... } public?class?School?{ private?String?name; private?String?address; ...... @Override public?String?toString()?{ //?TODO?Auto-generated?method?stub return?name+":"+address; } } public?class?SchoolTypeHandler?extends?BaseTypeHandler<School>?{ @Override public?void?setNonNullParameter(PreparedStatement?ps,?int?i, School?parameter,?JdbcType?jdbcType)?throws?SQLException?{ System.out.println("SchoolTypeHandlers??setParameter被調用了?i="+i+"\tjavaType="+parameter.getClass()+"\tjdbcType="+jdbcType); ps.setString(i,?parameter.toString()); } @Override public?School?getNullableResult(ResultSet?rs,?String?columnName) throws?SQLException?{ System.out.println("SchoolTypeHandlers??ResultSet?columnName"); School?school?=?new?School(); school.setName(rs.getString(columnName).split(":")[0]); school.setAddress(rs.getString(columnName).split(":")[1]); return?school; } @Override public?School?getNullableResult(ResultSet?rs,?int?columnIndex) throws?SQLException?{ System.out.println("SchoolTypeHandlers??ResultSet?columnIndex"); School?school?=?new?School(); school.setName(rs.getString(columnIndex).split(":")[0]); school.setAddress(rs.getString(columnIndex).split(":")[1]); return?school; } @Override public?School?getNullableResult(CallableStatement?cs,?int?columnIndex) throws?SQLException?{ System.out.println("CallableStatement?columnIndex被調用了"); return?null; } } public?class?UserTypeHandler?implements?TypeHandler?{ @Override public?void?setParameter(PreparedStatement?ps,?int?i,?Object?parameter, JdbcType?jdbcType)?throws?SQLException?{ System.out.println("One?setNonNullParameter被調用了?i="+i+"\tjavaType="+parameter.getClass()+"\tjdbcType="+jdbcType); if?(i?==?1) ps.setLong(i,?((User)parameter).getId()); else ps.setString(i,?((User)parameter).getName()); } @Override public?User?getResult(ResultSet?rs,?String?columnName) throws?SQLException?{ System.out.println("One?ResultSet?columnName被調用了"); User?u?=?new?User(); u.setName(rs.getString("name")); return?u; } @Override public?User?getResult(ResultSet?rs,?int?columnIndex)?throws?SQLException?{ System.out.println("One?ResultSet?columnIndex"); User?u?=?new?User(); u.setName(rs.getString("name")); return?u; } @Override public?User?getResult(CallableStatement?cs,?int?columnIndex) throws?SQLException?{ System.out.println("One?CallableStatement?columnIndex被調用了"); return?null; } }2014-12-11
public class User {
private long id ;
private String name;
private String password;
private String sex;
private String email;
private String tel;
private String department_name;
private String department_id;
private School school;
.......
}
public class School {
private String name;
private String address;
......
@Override public?String?toString()?{ //?TODO?Auto-generated?method?stub return?name+":"+address; } } public?class?SchoolTypeHandler?extends?BaseTypeHandler<School>?{ @Override public?void?setNonNullParameter(PreparedStatement?ps,?int?i, School?parameter,?JdbcType?jdbcType)?throws?SQLException?{ System.out.println("SchoolTypeHandlers??setParameter被調用了?i="+i+"\tjavaType="+parameter.getClass()+"\tjdbcType="+jdbcType); ps.setString(i,?parameter.toString()); } @Override public?School?getNullableResult(ResultSet?rs,?String?columnName) throws?SQLException?{ System.out.println("SchoolTypeHandlers??ResultSet?columnName"); School?school?=?new?School(); school.setName(rs.getString(columnName).split(":")[0]); school.setAddress(rs.getString(columnName).split(":")[1]); return?school; } @Override public?School?getNullableResult(ResultSet?rs,?int?columnIndex) throws?SQLException?{ System.out.println("SchoolTypeHandlers??ResultSet?columnIndex"); School?school?=?new?School(); school.setName(rs.getString(columnIndex).split(":")[0]); school.setAddress(rs.getString(columnIndex).split(":")[1]); return?school; } @Override public?School?getNullableResult(CallableStatement?cs,?int?columnIndex) throws?SQLException?{ System.out.println("CallableStatement?columnIndex被調用了"); return?null; } } public?class?UserTypeHandler?implements?TypeHandler?{ @Override public?void?setParameter(PreparedStatement?ps,?int?i,?Object?parameter, JdbcType?jdbcType)?throws?SQLException?{ System.out.println("One?setNonNullParameter被調用了?i="+i+"\tjavaType="+parameter.getClass()+"\tjdbcType="+jdbcType); if?(i?==?1) ps.setLong(i,?((User)parameter).getId()); else ps.setString(i,?((User)parameter).getName()); } @Override public?User?getResult(ResultSet?rs,?String?columnName) throws?SQLException?{ System.out.println("One?ResultSet?columnName被調用了"); User?u?=?new?User(); u.setName(rs.getString("name")); return?u; } @Override public?User?getResult(ResultSet?rs,?int?columnIndex)?throws?SQLException?{ System.out.println("One?ResultSet?columnIndex"); User?u?=?new?User(); u.setName(rs.getString("name")); return?u; } @Override public?User?getResult(CallableStatement?cs,?int?columnIndex) throws?SQLException?{ System.out.println("One?CallableStatement?columnIndex被調用了"); return?null; } }