spring+mybatis中typehandler怎么配置

来源:互联网 发布:steam汽车模拟软件 编辑:程序博客网 时间:2024/06/14 06:47

我们在不使用spring来管理的时候通常把typehandler的配置放到mybatis-config.xml中,如下:

<configuration>    <typeHandlers>      <!--           当配置package的时候,mybatis会去配置的package扫描TypeHandler          <package name="com.dy.demo"/>       -->      <!-- handler属性直接配置我们要指定的TypeHandler -->      <typeHandler handler=""/>      <!-- javaType 配置java类型,例如String, 如果配上javaType, 那么指定的typeHandler就只作用于指定的类型 -->      <typeHandler javaType="" handler=""/>      <!-- jdbcType 配置数据库基本数据类型,例如varchar, 如果配上jdbcType, 那么指定的typeHandler就只作用于指定的类型  -->      <typeHandler jdbcType="" handler=""/>      <!-- 也可两者都配置 -->      <typeHandler javaType="" jdbcType="" handler=""/>  </typeHandlers>  ......</configuration>

但是对于我们现在的开发环境来说,spring太流行了,所以这里就成了一块问题。
闲话不多说,直接上spring的配置:

    <!--声明TypeHandler bean-->    <bean id="myStringTypeHandler" class="util.MyStringTypeHandler"/>    <!-- 创建spring工厂 -->    <bean id="ssf" class="org.mybatis.spring.SqlSessionFactoryBean">        <!--data source的配置不变-->        <property name="dataSource" ref="ds"/>        <!--实体类别名-->        <property name="typeAliasesPackage" value="model"/>        <!--mapper文件注入-->        <property name="mapperLocations" value="classpath:/mybatis-mapper/*/*DaoImpl.xml"/>        <!--typeHandler注入-->        <property name="typeHandlers" ref="myStringTypeHandler"/>    </bean>

下面简单的介绍下typehandler的配置吧。
首先是官方对于这个属性的介绍:
页一
页二
以下是mybatis中转化string的源码:

package org.apache.ibatis.type;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class StringTypeHandler extends BaseTypeHandler<String> {    public StringTypeHandler() {    }    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {        ps.setString(i, parameter);    }    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {        return rs.getString(columnName);    }    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {        return rs.getString(columnIndex);    }    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {        return cs.getString(columnIndex);    }}

BaseTypeHandler源码:

package org.apache.ibatis.type;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import org.apache.ibatis.session.Configuration;public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {    protected Configuration configuration;    public BaseTypeHandler() {    }    public void setConfiguration(Configuration c) {        this.configuration = c;    }    public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {        if(parameter == null) {            if(jdbcType == null) {                throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");            }            try {                ps.setNull(i, jdbcType.TYPE_CODE);            } catch (SQLException var6) {                throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " + "Cause: " + var6, var6);            }        } else {            this.setNonNullParameter(ps, i, parameter, jdbcType);        }    }    public T getResult(ResultSet rs, String columnName) throws SQLException {        T result = this.getNullableResult(rs, columnName);        return rs.wasNull()?null:result;    }    public T getResult(ResultSet rs, int columnIndex) throws SQLException {        T result = this.getNullableResult(rs, columnIndex);        return rs.wasNull()?null:result;    }    public T getResult(CallableStatement cs, int columnIndex) throws SQLException {        T result = this.getNullableResult(cs, columnIndex);        return cs.wasNull()?null:result;    }    public abstract void setNonNullParameter(PreparedStatement var1, int var2, T var3, JdbcType var4) throws SQLException;    public abstract T getNullableResult(ResultSet var1, String var2) throws SQLException;    public abstract T getNullableResult(ResultSet var1, int var2) throws SQLException;    public abstract T getNullableResult(CallableStatement var1, int var2) throws SQLException;}

经过查看我们发现只需要实现BaseTypeHandler这个抽象类即可,记得泛型一定是String。
以下是我自己的代码,其中oracle数据库编码为ISO-8859-1,项目编码为GBK:

package util;import org.apache.ibatis.type.BaseTypeHandler;import org.apache.ibatis.type.JdbcType;import org.apache.log4j.Logger;import java.io.UnsupportedEncodingException;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;/** * 转化String的result与parameter * 注意:实现BaseTypeHandler时,泛型必须为String */public class MyStringTypeHandler extends BaseTypeHandler<String> {    private static final Logger log = Logger.getLogger(MyStringTypeHandler.class);    /**     * 转化字符串编码     * @param str     * @param oldCharset     * @param newCharset     * @return     */    private static String convertEncoding(String str,String oldCharset,String newCharset){        String resultStr = null;        try{            if (str == null) {                return resultStr;            }            resultStr = new String(str.getBytes(oldCharset),newCharset);        }catch(UnsupportedEncodingException e){            log.error(e.getMessage(),e);        }        return resultStr;    }    public MyStringTypeHandler() {    }    @Override    public void setNonNullParameter(PreparedStatement ps, int index, String parameter, JdbcType jdbcType) throws SQLException {        parameter = convertEncoding(parameter, "GBK","ISO-8859-1");        ps.setString(index,parameter);    }    @Override    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {        return convertEncoding(rs.getString(columnName),"ISO-8859-1","GBK");    }    @Override    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {        return convertEncoding(rs.getString(columnIndex),"ISO-8859-1","GBK");    }    @Override    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {        return convertEncoding(cs.getString(columnIndex),"ISO-8859-1","GBK");    }}

补充:以上可以解决正常的需求,但是大多码农都是不正常的,最近又遇到一个问题,也在这里加上。
当我们插入数据的时候,有些数据是可以为空的,MyBatis支持我们这样写:

<!--一个简单的插入语句--><insert id="insertUser">        insert into user            (id,username,password,address)        values            (#{id},            #{username}            #{password},            #{address,jdbcType=VARCHAR})    </insert>

这就会产生问题了,在我们加上了jdbcType=xxx这个配置后,MyBatis不再访问我们的TypeHandler,之后经过百度,发现可以使用如下几种方式解决:

<!--配置resultMap--><resultMap id="userResultMap" type="User">        <result typeHandler="StringTypeHandler" column="address" javaType="java.lang.String"                jdbcType="VARCHAR"                property="address"/>    </resultMap><!--调用--><select id="getUser" resultMap="userResultMap">        select * from user</select><!--这个方法的缺点在于配置比较繁琐,返回时配置resultMap,插入时配置parameterMap,还要设置每个对象的每一个属性-->
<!--这个方法简洁了很多,但是你想想我们有一个20多个字段的表,好吧,画面太美不敢想--><insert id="insertUser" parameterType="User">        INSERT INTO user(username,password,address) VALUES (#{username},#{password},#{address,javaType=String,jdbcType=VARCHAR,typeHandler=StringTypeHandler(这里注意要写类全名的)})    </insert>

我推荐下面这个方法,经过注解配置,数据库类型为xxx的,java类型为xxx的,都会经过这个转换类,果然注解才是好东西哇~
另外,你注意到注解中的值被用大括号括起来了么,这说明注解值可以是一个数组,就像我们这个字符转码类,
还能这样:@MapperJdbcTypes({JdbcType.VARCHAR,JdbcType.CHAR})
和这样:@MappedTypes({String.class,Character.class})
当然,我只是举个栗子,还是要看需求的

import org.apache.ibatis.type.MappedJdbcTypes;import org.apache.ibatis.type.MappedTypes;//这个注解定义的是JdbcType类型,这里的类型不可自己随意定义,必须要是枚举类org.apache.ibatis.type.JdbcType所枚举的数据类型@MappedJdbcTypes({JdbcType.VARCHAR})//这里定义的是JavaType的数据类型,描述了哪些Java类型可被拦截@MappedTypes({String.class})public class StringTypeHandler extends BaseTypeHandler<String> {...}

学习知识要晓出处,以上的配置jdbcType方法学习自http://blog.csdn.net/u012702547/article/details/54572679

如果有不对的地方,还请大神在下面评论区指导。当然,如果这些代码有什么疑问,也可以在下方留言。

0 0
原创粉丝点击