mybatis typehandler

建立TypeHandler

我们知道java有java的数据类型,数据库有数据库的数据类型,那么我们在往数据库中插入数据的时候是如何把java类型当做数据库类型插入数据库,在从数据库读取数据的时候又是如何把数据库类型当做java类型来处理呢?这中间必然要经过一个类型转换。在Mybatis中我们可以定义一个叫做TypeHandler类型处理器的东西,通过它可以实现Java类型跟数据库类型的相互转换。下面将就如何建立自己的TypeHandler做一个简要介绍。

TypeHandler接口

       在Mybatis中要实现自己的TypeHandler就需要实现Mybatis为我们提供的TypeHandler接口。在TypeHandler中定义了四个方法:

public interface TypeHandler<T> {  /** * 用于定义在Mybatis设置参数时该如何把Java类型的参数转换为对应的数据库类型 * @param ps 当前的PreparedStatement对象 * @param i 当前参数的位置 * @param parameter 当前参数的Java对象 * @param jdbcType 当前参数的数据库类型 * @throws SQLException */  void setParameter(PreparedStatement ps, int i, T parameter,  JdbcType jdbcType) throws SQLException;  /** * 用于在Mybatis获取数据结果集时如何把数据库类型转换为对应的Java类型 * @param rs 当前的结果集 * @param columnName 当前的字段名称 * @return 转换后的Java对象 * @throws SQLException */  T getResult(ResultSet rs, String columnName) throws SQLException;  /** * 用于在Mybatis通过字段位置获取字段数据时把数据库类型转换为对应的Java类型 * @param rs 当前的结果集 * @param columnIndex 当前字段的位置 * @return 转换后的Java对象 * @throws SQLException */  T getResult(ResultSet rs, int columnIndex) throws SQLException;  /** * 用于Mybatis在调用存储过程后把数据库类型的数据转换为对应的Java类型 * @param cs 当前的CallableStatement执行后的CallableStatement * @param columnIndex 当前输出参数的位置 * @return * @throws SQLException */  T getResult(CallableStatement cs, int columnIndex) throws SQLException;  }  

现在假设我们有一个实体对象User,其中有一个属性interests是String数组类型,如下所示:

public class User {  private int id;  private String name;  private int age;  private String[] interests;  public int getId() {  return id;  }  public void setId(int id) {  this.id = id;  }  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public String[] getInterests() {  return interests;  }  public void setInterests(String[] interests) {  this.interests = interests;  }  @Override  public String toString() {  return "User [age=" + age + ", id=" + id + ", interests="  + Arrays.toString(interests) + ", name=" + name + "]";  }  }  

我们需要把它以拼接字符串的形式存到数据库中,然后在取出来的时候又把它还原为一个String数组。这个时候我们就可以给它定义一个TypeHandler专门来处理String数组类型和数据库VARCHAR类型的相互转换。在这里我们建立一个名叫StringArrayTypeHandler的TypeHandler,代码如下所示:

package com.tiantian.mybatis.handler;  import java.sql.CallableStatement;  import java.sql.PreparedStatement;  import java.sql.ResultSet;  import java.sql.SQLException;  import java.sql.Types;  import org.apache.ibatis.type.JdbcType;  import org.apache.ibatis.type.TypeHandler;  public class StringArrayTypeHandler implements TypeHandler<String[]> {  public String[] getResult(ResultSet rs, String columnName)  throws SQLException {  String columnValue = rs.getString(columnName);  return this.getStringArray(columnValue);  }  public String[] getResult(ResultSet rs, int columnIndex)  throws SQLException {  String columnValue = rs.getString(columnIndex);  return this.getStringArray(columnValue);  }  public String[] getResult(CallableStatement cs, int columnIndex)  throws SQLException {  // TODO Auto-generated method stub  
String columnValue = cs.getString(columnIndex);  return this.getStringArray(columnValue);  }  public void setParameter(PreparedStatement ps, int i, String[] parameter,  JdbcType jdbcType) throws SQLException {  if (parameter == null)  ps.setNull(i, Types.VARCHAR);  else {  StringBuffer result = new StringBuffer();  for (String value : parameter)  result.append(value).append(",");  result.deleteCharAt(result.length()-1);  ps.setString(i, result.toString());  }  }  private String[] getStringArray(String columnValue) {  if (columnValue == null)  return null;  return columnValue.split(",");  }  }  

BaseTypeHandler抽象类

       在实现自己的TypeHandler时,除了上面提到的实现最原始的接口之外,Mybatis还为我们提供了一个实现了TypeHandler接口的抽象类BaseTypeHandler。所以我们也可以通过继承BaseTypeHandler来实现自己的TypeHandler。

       我们先来看一下BaseTypeHandler类的定义:

public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {  protected Configuration configuration;  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 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 {  setNonNullParameter(ps, i, parameter, jdbcType);  }  }  public T getResult(ResultSet rs, String columnName) throws SQLException {  T result = getNullableResult(rs, columnName);  if (rs.wasNull()) {  return null;  } else {  return result;  }  }  public T getResult(ResultSet rs, int columnIndex) throws SQLException {  T result = getNullableResult(rs, columnIndex);  if (rs.wasNull()) {  return null;  } else {  return result;  }  }  public T getResult(CallableStatement cs, int columnIndex) throws SQLException {  T result = getNullableResult(cs, columnIndex);  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;  }  

我们可以看到BaseTypeHandler对TypeHandler接口的四个方法做了一个简单的选择,把null值的情况都做了一个过滤,核心的取值和设值的方法还是抽象出来了供子类来实现。使用BaseTypeHandler还有一个好处是它继承了另外一个叫做TypeReference的抽象类,通过TypeReference的getRawType()方法可以获取到当前TypeHandler所使用泛型的原始类型。这对Mybatis在注册TypeHandler的时候是非常有好处的。在没有指定javaType的情况下,Mybatis在注册TypeHandler时可以通过它来获取当前TypeHandler所使用泛型的原始类型作为要注册的TypeHandler的javaType类型,这个在讲到Mybatis注册TypeHandler的方式时将讲到。

       当通过继承BaseTypeHandler来实现自己的TypeHandler时,我们的StringArrayTypeHandler应该这样写:

public class StringArrayTypeHandler extends BaseTypeHandler<String[]> {  @Override  public String[] getNullableResult(ResultSet rs, String columnName)  throws SQLException {  return getStringArray(rs.getString(columnName));  }  @Override  public String[] getNullableResult(ResultSet rs, int columnIndex)  throws SQLException {  return this.getStringArray(rs.getString(columnIndex));  }  @Override  public String[] getNullableResult(CallableStatement cs, int columnIndex)  throws SQLException {  return this.getStringArray(cs.getString(columnIndex));  }  @Override  public void setNonNullParameter(PreparedStatement ps, int i,  String[] parameter, JdbcType jdbcType) throws SQLException {  //由于BaseTypeHandler中已经把parameter为null的情况做了处理,所以这里我们就不用再判断parameter是否为空了,直接用就可以了  
StringBuffer result = new StringBuffer();  for (String value : parameter)  result.append(value).append(",");  result.deleteCharAt(result.length()-1);  ps.setString(i, result.toString());  }  private String[] getStringArray(String columnValue) {  if (columnValue == null)  return null;  return columnValue.split(",");  }  }

 

 

 

 

 

注册TypeHandler

       建立了自己的TypeHandler之后就需要把它注册到Mybatis的配置文件中,让Mybatis能够识别并使用它。注册TypeHandler主要有两种方式,一种是通过在Mybatis配置文件中定义typeHandlers元素的子元素typeHandler来注册;另一种是通过在Mybatis配置文件中定义typeHandlers元素的子元素package来注册。使用typeHandler子元素注册时一次只能注册一个TypeHandler,而使用package子元素注册时,Mybatis会把指定包里面的所有TypeHandler都注册为TypeHandler。使用typeHandler子元素注册时我们需要通过它的handler属性来指明当前要注册的TypeHandler的全名称,这个属性是必须要的。另外还有两个附加属性可以指定,一个是javaType,用以指定对应的java类型;另一个是jdbcType,用以指定对应的jdbc类型。使用package子元素注册时需要我们通过它的name属性来指定要扫描的包,如果这个时候我们也需要指定对应TypeHandler的javaType和jdbcType的话就需要我们在TypeHandler类上使用注解来定义了。Mybatis注册TypeHandler最基本的方式就是建立一个javaType、jdbcType和TypeHandler的对应关系。在使用typeHandler子元素进行注册的时候,有三种类型的注册方式:

1.如果我们指定了javaType和jdbcType,那么Mybatis会注册一个对应javaType和jdbcType的TypeHandler。

2.如果我们只指定了javaType属性,那么这个时候又分两种情况:

(1)如果我们通过注解的形式在TypeHandler类上用@MappedJdbcTypes指定了对应的jdbcType,那么Mybatis会一一注册指定的javaType、jdbcType和TypeHandler的组合,也包括使用这种形式指定了jdbcType为null的情况。现假设我们有如下这样一个StringArrayTypeHandler:

 

@MappedJdbcTypes({JdbcType.VARCHAR})  public class StringArrayTypeHandler implements TypeHandler<String[]> {  //..中间的实现代码省略了  //..  

}  

然后我们在Mybatis的配置文件中这样注册它:

<typeHandlers>  <typeHandler handler="com.tiantian.mybatis.handler.StringArrayTypeHandler" javaType="[Ljava.lang.String;"/>  </typeHandlers>  

则Mybatis在实际注册的时候是以javaType为String数组,jdbcType为VARCHAR来注册StringArrayTypeHandler的。

 

转载于:https://www.cnblogs.com/Dhouse/p/5977039.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/489770.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java图片压缩不失真_软件分享 | Lit图片压缩

软件分享01软件名称Lit图片压缩02软件版本V1.2.0.01603软件简介Lit图片压缩app是一款免费简单好用的图片压缩工具&#xff0c;让图片在不失真的情况下&#xff0c;进行压缩和裁剪&#xff0c;轻松就能压缩成你想要的尺寸&#xff0c;并且原来的像素不失真&#xff0c;保持原画质…

从大型主机到个人计算机:机器人产业可以从pc普及革命中学到什么?

来源&#xff1a;大数据文摘出品自主化机器人已逐渐变得无处不在。自动吸尘器、自动割草机、会简单交互的小玩具&#xff0c;以及呼之欲出的自动驾驶汽车&#xff0c;都可以看作是一个能实现某种自动功能的机器人。一辈接着一辈&#xff0c;我们一直在期待出现《星球大战》中的…

【Poj1017】Packets

http://poj.org/problem?id1017 艰难啊 弄了很久咧 拍了几十万组,以后拍要多组数据 Solution 从大wangxiaofang 从大往小放,有空余的从大往小填 注意细节 Notice b<0的情况,还有就是当前填充完了,还剩一点给下一个(小一点的)填 Code // This file is made by YJinpeng&…

vb上传文件到MySQL_ASP.NET上传文件到数据库VB版

代码如下&#xff1a;敬请过目&#xff01;If Me.FileUpload1.PostedFile.ContentLength > 0 ThenDim cn As New Data.OleDb.OleDbConnectionDim dc As Data.OleDb.OleDbCommandDim para As Data.OleDb.OleDbParameterDim SQL, FileName As String连线字符串cn.ConnectionSt…

python爬虫框架论文开题报告范文_研究思路及框架--开题报告

三、研究的思路、论文框架本文采取文献研究、定性研究、定量研究、计量研究等研究方法&#xff0c;紧紧围绕“宁波对外贸易对产业结构升级的影响”这一主题展开&#xff0c;在研究国内外关于这方面的文献的基础上&#xff0c;深入分析在一个开放经济中宁波对外贸易可以通过哪些…

构建超级智能未来系统的三原则

《崛起的超级智能》作者&#xff0c;计算机博士刘锋前言&#xff1a;科技领域看不见的手在过去50年促使互联网从网状结构进化成为大脑模型&#xff0c;而人类群体智慧与机器群体智能通过这个互联网大脑架构形成人类前所未有的超级智能形式。在构建互联网大脑模型成熟状态的过程…

游戏“冰川滑行”设计稿(第一版)

名称&#xff1a;&#xff08;暂定&#xff09;冰川滑行 游戏类型&#xff1a;关卡式迷宫 基本规则&#xff1a;在迷宫中可以向上下左右方向移动&#xff0c;每次移动只能在碰到障碍物或到达无冰区停止&#xff1b;从入口进入&#xff0c;从出口离开为胜利。 地形种类&#xff…

mysql授予权限和撤销权限的关系_MySQL数据库常用的授予权限和撤销权限的命令讲解...

MySQL 赋予用户权限命令的简单格式可概括为&#xff1a;一、grant 普通数据用户&#xff0c;查询、插入、更新、删除 数据库中所有表数据的权利1 2 3 4grant select on testdb.* to common_user% grant insert on testdb.* to common_user% grant update on testdb.* to common…

spring的aop_Spring AOP 小结

1. AOP专业概述在软件行业&#xff0c;AOP为Aspect Oriented Programming的缩写&#xff0c;意思为&#xff1a;面向切面编程&#xff0c;通过预编译方法和运行期动态代理实现程序功能的统一维护的一种技术。要理解切面变成&#xff0c;就需要先理解什么是切面。用刀把一个西瓜…

【解析】工业机器人中的各类传感器技术应用

来源&#xff1a;中国机器人网前言工业机器人涉及到的传感器有哪些&#xff1f;2012年&#xff0c;美国提出“工业互联网”&#xff0c;2013年&#xff0c;德国提出“工业4.0”&#xff0c;2015年&#xff0c;中国提出“中国制造2025”。在工业物联网、AR、云计算等技术热潮下&…

java水果超市mysql_Java基础 | 项目实战之水果超市

传智播客线上平台博学谷启动项目实战&#xff0c;在学习过程中真正还原企业实际开发流程及团队配合&#xff0c;同时对所学知识最大化吸收项目启动准备01规定学习位置参加项目实战&#xff0c;学习位置不能小于当前标注的位置02项目分组本次Java基础参加项目实战的同学较多&…

android dp sp px_Android屏幕适配★★重点盘点★★

引言屏幕适配是 android 开发/面试 绕不开的一个问题。本文 将屏幕适配的知识要点完整展现给各位读者。正文大纲android需要做屏幕适配的原因基础知识点(★★★很重要★★★)屏幕适配攻略正文↓↓↓android需要做屏幕适配的原因关键字&#xff1a;android碎片化android面世以来…

AI与网络安全的未来:数据集与协同能力

来源&#xff1a;安全牛有关 AI 优势与风险的争论如今已成媒体日常&#xff0c;很多此类讨论都集中在潜在负面影响上&#xff0c;话题范围从工作自动化导致广泛失业到 AI 用于创建 “深度伪造” 视频。但另一方面&#xff0c;我们已经在享受 AI 自动化助手的正面效果所带来的种…

GIS-013-Cesium Terrain 数据生成

一、Python 1、修改Python脚本文件 if __name____main__: #sys.argv [F:\\000_Terrain\\T7-gdal2srtmtiles-demo.py, --cesium, --resume, -z, 0-8, -p, geodetic, F:\\50_GIS\\4000_Data\\world_raster\\Day.tif, F:\000_Terrain\\terrain_tiles] sys.argv [F:\\000_Terrain…

如何在linux下yum安装mysql_linux下使用yum安装mysql详解

1、安装客户端和服务器端确认mysql是否已安装&#xff1a;yum list installed mysql*rpm -qa | grep mysql*查看是否有安装包&#xff1a;yum list mysql*安装mysql客户端&#xff1a;yum install mysql安装mysql 服务器端&#xff1a;yum install mysql-serveryum install mys…

ucinet计算聚类系数大于1怎么办_聚类性能评估-ARI(调兰德指数)

注意&#xff1a;ARI取值范围为[-1,1]&#xff0c;值越大越好&#xff0c;反映两种划分的重叠程度&#xff0c;使用该度量指标需要数据本身有类别标记。用C表示实际的类别划分&#xff0c;K表示聚类结果。定义a 为在C中被划分为同一类&#xff0c;在K中被划分为同一簇的实例对数…

这才是未来真正的风口,一文看清13种硬科技投资趋势

来源&#xff1a;资本实验室如果非要说“风口”&#xff0c;那么在未来10年乃至20年&#xff0c;硬科技就是最大的风口。近期&#xff0c;由麻省理工学院创建的非盈利投资机构The Engine与投资研究机构Pitchbook联合发布了一份名为《2019硬科技图景》的研究报告。该报告将硬科技…

sleep(),wait(),yield(),notify()

sleep()&#xff0c;wait()&#xff0c;yield() 的区别 sleep方法和yield方法是Thread类的方法&#xff0c;wait方法是Object的方法。 sleep 方法使当前运行中的线程睡眼一段时间&#xff0c;进入不可运行状态&#xff0c;这段时间的长短是由程序设定的&#xff0c;不会释放锁标…

mysql 滚屏查看查询结果_MySQL_查询操作(select)

查询操作1、别名查询select id 序号,name名字from test_1209ryc;2、条件查询(between)select * from test_1209ryc where id between 2 and 5;3、条件查询(in)select * from test_1209ryc where id in(1,2,3);4、子查询select * from test_1209ryc where id in (select id from…

new arraylist内存_如何避免内部类中的内存泄漏

我先假设读者已经熟悉在Java代码中使用嵌套类的基础知识。在本文里&#xff0c;我将展示嵌套类的陷阱&#xff0c;内部类在JVM中引起内存泄漏和内存不足错误的地方。之所以会发生这种类型的内存泄漏&#xff0c;是因为内部类必须始终能够访问其外部类。从简单的嵌套过程到内存不…