欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

mybatis的typeHandler

程序员文章站 2022-04-24 10:12:28
typeHandler作用: 1.传参时将javaType类型转换成jdbcType 2.结果集中ResultSet中取值时,jdbcType转换为javaType; 系统自定义的typeHandler: mybatis系统内部定义了一系列的typeHandler;基本涵盖了我们正常使用的类型转换; ......

typehandler作用:

  1.传参时将javatype类型转换成jdbctype

  2.结果集中resultset中取值时,jdbctype转换为javatype;

系统自定义的typehandler:

  mybatis系统内部定义了一系列的typehandler;基本涵盖了我们正常使用的类型转换;如下

mybatis的typeHandler

选取一个系统自定义的typehandler看看;

在包org.apache.ibatis.type下有一个stringtypehandler.java

源码如下:

mybatis的typeHandler
public class stringtypehandler extends basetypehandler<string> {

  @override
  public void setnonnullparameter(preparedstatement ps, int i, string parameter, jdbctype jdbctype)
      throws sqlexception {
    ps.setstring(i, parameter);
  }

  @override
  public string getnullableresult(resultset rs, string columnname)
      throws sqlexception {
    return rs.getstring(columnname);
  }

  @override
  public string getnullableresult(resultset rs, int columnindex)
      throws sqlexception {
    return rs.getstring(columnindex);
  }

  @override
  public string getnullableresult(callablestatement cs, int columnindex)
      throws sqlexception {
    return cs.getstring(columnindex);
  }
}
view code

stringtypehandler继承了basetypehandler;而basetypehandler实现了接口typehandler,

basetypehandler中代码

mybatis的typeHandler
/**
 *    copyright 2009-2015 the original author or authors.
 *
 *    licensed under the apache license, version 2.0 (the "license");
 *    you may not use this file except in compliance with the license.
 *    you may obtain a copy of the license at
 *
 *       http://www.apache.org/licenses/license-2.0
 *
 *    unless required by applicable law or agreed to in writing, software
 *    distributed under the license is distributed on an "as is" basis,
 *    without warranties or conditions of any kind, either express or implied.
 *    see the license for the specific language governing permissions and
 *    limitations under the license.
 */
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.executor.result.resultmapexception;
import org.apache.ibatis.session.configuration;

/**
 * @author clinton begin
 * @author simone tripodi
 */
public abstract class basetypehandler<t> extends typereference<t> implements typehandler<t> {

  protected configuration configuration;

  public void setconfiguration(configuration c) {
    this.configuration = c;
  }

  @override
  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 e) {
        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: " + e, e);
      }
    } else {
      try {
        setnonnullparameter(ps, i, parameter, jdbctype);
      } catch (exception e) {
        throw new typeexception("error setting non null for parameter #" + i + " with jdbctype " + jdbctype + " . " +
                "try setting a different jdbctype for this parameter or a different configuration property. " +
                "cause: " + e, e);
      }
    }
  }

  @override
  public t getresult(resultset rs, string columnname) throws sqlexception {
    t result;
    try {
      result = getnullableresult(rs, columnname);
    } catch (exception e) {
      throw new resultmapexception("error attempting to get column '" + columnname + "' from result set.  cause: " + e, e);
    }
    if (rs.wasnull()) {
      return null;
    } else {
      return result;
    }
  }

  @override
  public t getresult(resultset rs, int columnindex) throws sqlexception {
    t result;
    try {
      result = getnullableresult(rs, columnindex);
    } catch (exception e) {
      throw new resultmapexception("error attempting to get column #" + columnindex+ " from result set.  cause: " + e, e);
    }
    if (rs.wasnull()) {
      return null;
    } else {
      return result;
    }
  }

  @override
  public t getresult(callablestatement cs, int columnindex) throws sqlexception {
    t result;
    try {
      result = getnullableresult(cs, columnindex);
    } catch (exception e) {
      throw new resultmapexception("error attempting to get column #" + columnindex+ " from callable statement.  cause: " + e, e);
    }
    if (cs.wasnull()) {
      return null;
    } else {
      return result;
    }
  }

  public abstract void setnonnullparameter(preparedstatement ps, int i, t parameter, jdbctype jdbctype) throws sqlexception;

  public abstract t getnullableresult(resultset rs, string columnname) throws sqlexception;

  public abstract t getnullableresult(resultset rs, int columnindex) throws sqlexception;

  public abstract t getnullableresult(callablestatement cs, int columnindex) throws sqlexception;

}
view code

 

getresult分别用columnname和columnindex从resultset中获取数据,callablestatement表示从存储过程中获取结果及数据的方法;

下面我们创建自定义typehandler

mybatis的typeHandler

rolemapper.java

mybatis的typeHandler
package com.learn.charter2.mapper;

import java.util.list;

import com.learn.charter2.po.role;

public interface rolemapper {
    role getrole(long id) throws exception;
    int deleterole(long id) throws exception;
    int insertrole(role role) throws exception;
    list<role> findrole(role role) throws exception;
}
view code

role.java

mybatis的typeHandler
package com.learn.charter2.po;

public class role {
    private long id;
    private string rolename;
    private string note;
    private integer pk;
    
    public long getid() {
        return id;
    }
    public void setid(long id) {
        this.id = id;
    }
    public string getrolename() {
        return rolename;
    }
    public void setrolename(string rolename) {
        this.rolename = rolename;
    }
    public string getnote() {
        return note;
    }
    public void setnote(string note) {
        this.note = note;
    }
    public integer getpk() {
        return pk;
    }
    public void setpk(integer pk) {
        this.pk = pk;
    }
    

    

}
view code

sqlsessionfactoryutil.java

mybatis的typeHandler
package com.learn.charter2.util;

import java.io.inputstream;
import java.util.logging.level;
import java.util.logging.logger;

import org.apache.ibatis.io.resources;
import org.apache.ibatis.session.sqlsession;
import org.apache.ibatis.session.sqlsessionfactory;
import org.apache.ibatis.session.sqlsessionfactorybuilder;

public class sqlsessionfactoryutil {
    private static sqlsessionfactory sqlsessionfactory=null;
    private static final class class_lock=sqlsessionfactoryutil.class;
    private sqlsessionfactoryutil() {
    }
    public static sqlsessionfactory initsqlsessionfactory(){
        string resource="mybatis-config.xml";
        inputstream inputstream=null;
        try {
            inputstream=resources.getresourceasstream(resource);
        } catch (exception e) {
            logger.getlogger(sqlsessionfactoryutil.class.getname()).log(level.severe,null,e);
        }
        synchronized (class_lock) {
            if(sqlsessionfactory==null){
                sqlsessionfactory=new sqlsessionfactorybuilder().build(inputstream);
            }
        }
        return sqlsessionfactory;
    }
    public static sqlsession opensqlsession(){
        if(sqlsessionfactory==null){
            initsqlsessionfactory();
        }
        return sqlsessionfactory.opensession();
    }
}
view code

log4j.properties

log4j.rootlogger=debug,stdout
log4j.logger.org.mybatis=debug
log4j.appender.stdout=org.apache.log4j.consoleappender
log4j.appender.stdout.layout=org.apache.log4j.patternlayout
log4j.appender.stdout.layout.conversionpattern=%5p %d %c:%m%n

 

mybatis-config.xml

 1 <?xml version="1.0" encoding="utf-8" ?> <!doctype configuration  public "-//mybatis.org//dtd config 3.0//en"  "http://mybatis.org/dtd/mybatis-3-config.dtd">
 2 <configuration>
 3     <typehandlers>
 4         <typehandler handler="com.learn.charter2.util.mystringtypehandler" javatype="string" jdbctype="varchar"/>
 5         <typehandler handler="com.learn.charter2.util.myintergertypehandler" javatype="int" jdbctype="varchar"/>
 6     </typehandlers>
 7     <environments default="development">
 8         <environment id="development">
 9             <transactionmanager type="jdbc">
10                 <property name="autocommit" value="false" />
11             </transactionmanager>
12             <datasource type="pooled">
13                 <property name="driver" value="com.mysql.jdbc.driver" />
14                 <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
15                 <property name="username" value="root" />
16                 <property name="password" value="gys" />
17             </datasource>
18         </environment>
19     </environments>
20     <mappers>
21         <mapper resource="com/learn/charter2/mapper/rolemapper.xml" />
22     </mappers>
23 </configuration>

 

rolemapper.xml

 1 <?xml version="1.0" encoding="utf-8" ?> <!doctype mapper  public "-//mybatis.org//dtd mapper 3.0//en"  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 2 <mapper namespace="com.learn.charter2.mapper.rolemapper">
 3     
 4     <resultmap type="com.learn.charter2.po.role" id="rolemap">
 5         <id column="id" property="id" javatype="long" jdbctype="bigint"/>
 6         <result column="role_name" property="rolename" javatype="string" jdbctype="varchar"/>
 7         <result column="note" property="note" typehandler="com.learn.charter2.util.mystringtypehandler"/>
 8         <result column="pk" property="pk" typehandler="com.learn.charter2.util.myintergertypehandler"/>
 9     </resultmap>
10 
11 
12     <select id="getrole" parametertype="long" resultmap="rolemap"> 
13     select id,role_name as rolename,note from t_role where id=#{id}
14     </select>
15     
16     <select id="findrole" parametertype="com.learn.charter2.po.role" resultmap="rolemap"> 
17     select id,role_name as rolename,note,pk from t_role 
18     <where>
19         <if test="rolename !=null">
20              role_name like concat('%',#{rolename,javatype=string,jdbctype=varchar,typehandler=com.learn.charter2.util.mystringtypehandler},'%')
21         </if>
22         <if test="pk !=null">
23         and pk =#{pk,javatype=int,jdbctype=varchar,typehandler=com.learn.charter2.util.myintergertypehandler}
24          </if> 
25     </where>    
26 
27 
28     </select>
29     
30     <insert id="insertrole" parametertype="com.learn.charter2.po.role">
31         insert into t_role
32         (role_name,note)
33         values
34         (#{rolename},#{note})
35     </insert>
36     <delete id="deleterole" parametertype="long">
37         delete from t_role where id=#{id}
38     </delete>
39 </mapper>

myintergertypehandler.java

 1 package com.learn.charter2.util;
 2 
 3 
 4 import java.sql.callablestatement;
 5 import java.sql.preparedstatement;
 6 import java.sql.resultset;
 7 import java.sql.sqlexception;
 8 
 9 import org.apache.ibatis.type.jdbctype;
10 import org.apache.ibatis.type.mappedjdbctypes;
11 import org.apache.ibatis.type.mappedtypes;
12 import org.apache.ibatis.type.typehandler;
13 import org.apache.log4j.logger;
14 
15 import sun.security.action.getintegeraction;
16 
17 
18 /**
19  * @mappedtypes({integer.class})
20    @mappedjdbctypes(jdbctype.varchar)
21  *
22  */
23 public class myintergertypehandler implements typehandler<integer> {
24     
25     private logger log=logger.getlogger(myintergertypehandler.class);
26 
27     private int getint(string v){
28         if("a".equals(v)){
29             return 10;
30         }else if("b".equals(v)){
31             return 20;
32         }else if("c".equals(v)){
33              return 30;
34         }else{
35             return 60;
36         }
37     }
38     @override
39     public integer getresult(callablestatement cs, int index)
40             throws sqlexception {
41         log.info("使用我的integertypehandler,callblestatment下表获取字符串");
42         return getint(cs.getstring(index));
43     }
44 
45     @override
46     public integer getresult(resultset rs, int index) throws sqlexception {
47         log.info("使用我的integertypehandler,resultset下标获取字符串");
48         return getint(rs.getstring(index));
49     }
50 
51     @override
52     public integer getresult(resultset rs, string colname) throws sqlexception {
53         log.info("使用我的integertypehandler,resultset 列名获取字符串");
54         return getint(rs.getstring(colname));
55     }
56 
57     @override
58     public void setparameter(preparedstatement ps, int index, integer value,jdbctype jt) throws sqlexception {
59         log.info("使用我的integertypehandler==index:"+index+";value:"+value);
60         string v="";
61         if(value==1){
62             v="a";
63         }else if(value==2){
64             v="b";
65         }else if(value==3){
66             v="c";
67         }else {
68             v="guoyansi";
69         }
70         ps.setstring(index, v);
71     }
72 }

mystringtypehandler.java

 1 package com.learn.charter2.util;
 2 
 3 
 4 import java.sql.callablestatement;
 5 import java.sql.preparedstatement;
 6 import java.sql.resultset;
 7 import java.sql.sqlexception;
 8 
 9 import org.apache.ibatis.type.jdbctype;
10 import org.apache.ibatis.type.mappedjdbctypes;
11 import org.apache.ibatis.type.mappedtypes;
12 import org.apache.ibatis.type.typehandler;
13 import org.apache.log4j.logger;
14 
15 
16 @mappedtypes({string.class})
17 @mappedjdbctypes(jdbctype.integer)
18 public class mystringtypehandler implements typehandler<string> {
19     private logger log=logger.getlogger(mystringtypehandler.class);
20     
21     @override
22     public string getresult(callablestatement cs, int index)
23             throws sqlexception {
24         log.info("使用我的stringtypehandler,callblestatment下表获取字符串");
25         return cs.getstring(index);
26     }
27 
28     @override
29     public string getresult(resultset rs, int index) throws sqlexception {
30         log.info("使用我的stringtypehandler,resultset下标获取字符串");
31         return rs.getstring(index);
32     }
33 
34     @override
35     public string getresult(resultset rs, string colname) throws sqlexception {
36         log.info("使用我的stringtypehandler,resultset 列名获取字符串");
37         return rs.getstring(colname);
38     }
39 
40     @override
41     public void setparameter(preparedstatement ps, int index, string value,
42             jdbctype jt) throws sqlexception {
43         value=value+"m";
44         log.info("使用我的stringtypehandler==index:"+index+";value:"+value);
45         ps.setstring(index, value);
46     }
47     
48     
49 }

charter2main.java

 1 package com.learn.charter2.main;
 2 
 3 import java.util.list;
 4 
 5 import org.apache.ibatis.session.sqlsession;
 6 
 7 import com.learn.charter2.mapper.rolemapper;
 8 import com.learn.charter2.po.role;
 9 import com.learn.charter2.util.sqlsessionfactoryutil;
10 
11 public class charter2main {
12     public static void main(string[] args) {
13         sqlsession sqlsession = null;
14         try {
15             sqlsession = sqlsessionfactoryutil.opensqlsession();
16             rolemapper rolemapper = sqlsession.getmapper(rolemapper.class);
17             role role = new role();
18             role.setpk(10);
19             list<role> list=rolemapper.findrole(role);
20             for(role r:list){
21                 system.out.println("id:"+r.getid()+";rolename:"+r.getrolename()+";note:"+r.getnote()+";pk:"+r.getpk());
22             }
23         } catch (exception e) {
24             system.err.println(e.getmessage());
25             sqlsession.rollback();
26         }finally{
27             if(sqlsession!=null){
28                 sqlsession.close();
29             }
30         }
31     }
32 
33 }

自定义typehandler的三个步骤:

1.定义typehandler(myintergertypehandler.java     mystringtypehandler.java)

2.配置typehandler(mybatis-config.xml中3-6行)

3.指定入参中哪个字段使用typehandler(mapper.xml中19-24行)

4.指定出参中哪个字段使用typehandler(mapper.xml中7-8行)

以myintergertypehandler为例,运行一下charter2main.java

mybatis的typeHandler

charter2main 中传入的pk参数是10,被typehandler默默的转换成了guoyansi;
因为guoyansi在数据库中找到了值,在被返回到java中,guoyansi又被typehandler转化成了60;
这个例子展示的就是integer和string之间的转换。