镜幻
2014-12-10 13:39
<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。。。。你怎么看?
但如果是你来设计typeHandler的解析过程,它首先是要对你的User参数进行类型转换的,转换后肯定不再是User了(要不然你也不会进行类型转换了),这个时候你又如何用#{school}来和转换后的类型进行匹配呢,你可能会说,当我用typeHandler=com.user.type.SchoolTypeHandler的时候它就不应该再做类型转换而把原来的类型给我,可这样另一处#{id}应该是用转换后的类型,那这样经过UserTypeHandler后,竟然还需要同时保持转换前与转换后两种类型,如果是你你会这样设计吗?不敢说mybaits的方式是perfect,但你该如何设计才能即达到你说的局部配置覆盖全局的效果,又能不让typeHandler的效果让人感到歧义?不管讨论的结果如何,我个人很赞赏你这种钻研的精神和清晰的分析思路,用不了多久你就不用在这里和我讨论了。:)
我明白你的代码结构与逻辑了,不能说是他逻辑上有问题,只能说你的代码结构导致了这样互相干扰的情况
你的类型转换器的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拿到的类型,为这些#{}赋值的控制,已经和你想的不一样了。
我需要看下user的类结构
我也碰到相同的问题,User的所有属性都用UserTypeHandler去处理,请问楼主最后怎么解决的
我已经查过了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 } } } }
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; } }
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; } }
通过自动回复机器人学Mybatis---基础版
107412 学习 · 786 问题
相似问题