MyBatis中TypeHandler的使用教程

news2025/1/11 15:06:01

一.TypeHandler作用及其使用场景

在我们平常开发操作数据库时,查询、插入数据等操作行为,有时会报数据类型不匹配异常,就可以得知数据的类型是不唯一的必然是多种不同的数据类型。并且我们必须要明确的一点就是java作为一门编程语言有自己的数据类型,数据库也是有自己的数据类型的。

jdbc数据类型:org.apache.ibatis.type.JdbcType 此枚举就是所有的数据库支持类型

java数据类型:int、long、string、…

一定要分清,例如java重的date数据插入到数据库中,应该是已经转换成了数据库的某种类型,必然跟java已经没有关系了。中间有一些我们看不见的操作做了数据处理。

假设此时的java类型与数据库数据类型是一样的,哪么其他语言中的日期数据插入数据库时又该怎么解释,例如C#操作数据库存入时间类型,C#与java肯定没有关系吧。所以每种语言与数据库之间有种数据类型关系对应。

思考:

因为java与数据库各自有数据类型,所以在将java数据存入数据库前中间是否有其他操作,是我们看不见的,不然java数据怎么知道自己与哪个jdbc数据类型匹配?

答:mybatis框架为每种数据类型做了默认的关系对应,BaseTypeHandler的所有实现类,就是来做这些处理的。

例如:java中的date插入数据库时是jdbc哪种类型,怎么就是这种类型? 中间具体有什么操作?

答:DateTypeHandler就是来解决date数据类型的处理。

二.TypeHandler使用

我们想要自定义去处理Java和JDBC的数据类型转换时,需要实现TypeHandler接口,该接口源码如下:

//此接口作用是用于指定jdbc与java的数据类型间对应关系处理。
public interface TypeHandler<T> {
  // 保存操作,数据入库之前时数据处理
  void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
  //下面三个则是,从数据库加载数据后,vo对象封装前的数据处理
  T getResult(ResultSet rs, String columnName) throws SQLException;
  T getResult(ResultSet rs, int columnIndex) throws SQLException;
  T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}

假如现在需要将list字段插入到数据库前转换成varchar,即list [1,2,3] ==》varchar 1,2,3,并且从数据库中加载到程序时自动转换从list类型,实现代码如下:

1.编写typehandler实现类,制定转换规则

package com.cjy.mybatis.typehandler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import org.apache.log4j.Logger;

@MappedJdbcTypes(JdbcType.VARCHAR)  //数据库类型
@MappedTypes({List.class})            //java数据类型
public class ListTypeHandler implements TypeHandler<List<String>>{

    private Logger logger = Logger.getLogger(ListTypeHandler.class);
    
    @Override
    public void setParameter(PreparedStatement ps, int i,
            List<String> parameter, JdbcType jdbcType) throws SQLException {
        logger.info("method ====>>> setParameter");
        String hobbys = dealListToOneStr(parameter);
        ps.setString(i , hobbys);
    }

    /**
     * 集合拼接字符串
     * @param parameter
     * @return
     */
    private String dealListToOneStr(List<String> parameter){
        if(parameter == null || parameter.size() <=0)
            return null;
        String res = "";
        for (int i = 0 ;i < parameter.size(); i++) {
            if(i == parameter.size()-1){
                res+=parameter.get(i);
                return res;
            }
            res+=parameter.get(i)+",";
        }
        return null;
    }
    //
    @Override
    public List<String> getResult(ResultSet rs, String columnName)
            throws SQLException {
        logger.info("method ====>>> getResult(ResultSet rs, String columnName)");
        return Arrays.asList(rs.getString(columnName).split(","));
    }

    @Override
    public List<String> getResult(ResultSet rs, int columnIndex)
            throws SQLException {
        logger.info("method ====>>> getResult(ResultSet rs, int columnIndex)");
          return Arrays.asList(rs.getString(columnIndex).split(","));
    }

    @Override
    public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException{
        logger.info("method ====>>> getResult(CallableStatement cs, int columnIndex)");
        String hobbys = cs.getString(columnIndex);
        return Arrays.asList(hobbys.split(","));
    }
}

2.配置mybatis xml文件

<typeHandler javaType="list" jdbcType="VARCHAR" handler="com.cjy.mybatis.typehandler.ListTypeHandler"/>

3.编写sql

  <select id="selectEmp" resultType="com.cjy.mybatis.entity.Employee" parameterType="int">
    select id,user_name userName,gender,email,hobbys,createtime from employee where id = #{id}
  </select>
  
  <insert id="saveEmpOne" parameterType="com.cjy.mybatis.entity.Employee" >
  <!-- or parameterMap="parameMap" -->
      INSERT INTO employee(user_name,gender,email,createtime,hobbys) 
      VALUES(#{userName},#{gender},#{email},#{createtime,typeHandler=com.cjy.mybatis.typehandler.MyDateTypeHandler},
      #{hobbys,typeHandler=com.cjy.mybatis.typehandler.ListTypeHandler})
      <!--数据插入前:对hobbys做数据格式转换。  -->
  </insert>

4.测试代码

    @Test
    public void test2(){
        SqlSessionFactory sqlSessionFactory = MySqlSessionFacoty.getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
         Employee employee = new Employee(null, "yanjiu", "1", "yanjiu@163.com", new Date(),Arrays.asList(new String[]{"yuwen","shuxue","yingyu","zhengzhi"}));
         EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
         int saveEmpOne = mapper.saveEmpOne(employee);
         System.out.println(saveEmpOne+"-------------------");
         openSession.commit();
         openSession.close();
    }

测试结果:

查询数据测试varchar–》list 转换::

    @Test
    public void test5(){
        SqlSessionFactory sqlSessionFactory = MySqlSessionFacoty.getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
         EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
         Employee selectEmp = mapper.selectEmp(10);
         System.out.println(selectEmp);
/**数据加载成功
2019-07-24 15:08:02 INFO  com.cjy.mybatis.typehandler.ListTypeHandler - method ====>>> getResult(ResultSet rs, String columnName)
2019-07-24 15:08:02 INFO  com.cjy.mybatis.typehandler.MyDateTypeHandler - getResult(ResultSet rs, String columnName)....
Employee [id=10, userName=yanjiu, gender=1, email=yanjiu@163.com, createtime=Wed Jul 24 15:05:58 CST 2019, hobbys=[yuwen, shuxue, yingyu, zhengzhi]]
 */
    }

三.typeHandlers注册方式

  1. 单个注册:typeHandler 标签指定handler 全类名

  1. 多个注册:指定多个单个注册方式;或者使用package 标签

  <typeHandlers>
         <!-- <typeHandler javaType="list" jdbcType="VARCHAR" handler="com.cjy.mybatis.typehandler.ListTypeHandler"/>
         <typeHandler javaType="Date" jdbcType="VARCHAR" handler="com.cjy.mybatis.typehandler.MyDateTypeHandler"/> -->
         <package name="com.cjy.mybatis.typehandler"/>
         <!--
         typeHandler: 单个注册方式
         package:多个注册方式
           -->
  </typeHandlers>

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

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

相关文章

如何使用ElementUI的table组件来实现单元格的行合并

前言 最近在编写一个值班的排班表&#xff0c;然后中间涉及到了表格应用。并且还要做出类似这种效果的行合并效果: 然后就开始找组件了。Html的table是有rowsSpan和colsSpan的属性来实现行合并和列合并的。然后就在网上找资料&#xff0c;发现没有几篇能把这两个属性将好的&a…

LeetCode刷题模版:111 - 120

目录 简介111. 二叉树的最小深度112. 路径总和113. 路径总和 II114. 二叉树展开为链表115. 不同的子序列116. 填充每个节点的下一个右侧节点指针117. 填充每个节点的下一个右侧节点指针 II118. 杨辉三角119. 杨辉三角 II120. 三角形最小路径和结语简介 Hello! 非常感谢您阅读海…

SWPUCTF 2022新生赛 web部分wp

&#x1f60b;大家好&#xff0c;我是YAy_17&#xff0c;是一枚爱好网安的小白。 本人水平有限&#xff0c;欢迎各位大佬指点&#xff0c;一起学习&#x1f497;&#xff0c;一起进步⭐️。⭐️此后如竟没有炬火&#xff0c;我便是唯一的光。⭐️ 目录 [SWPUCTF 2022 新生赛]…

linux中使用KubeSphere和集群k8s 部署springboot项目

上期已经介绍了单体k8s部署springboot项目&#xff0c;这期讲解集群k8s部署springboot项目 因为部署方式已经在单体中讲过&#xff0c;现在大体粗略讲一下首先看下集群节点&#xff0c;如下所示&#xff1a; 第一步&#xff1a;创建项目----》按照做的项目名称建 创建后&…

MyCat实现单库分表+代理所有表

MyCAT支持水平分片与垂直分片&#xff1a; 水平分片&#xff1a;一个表格的数据分割到多个节点上&#xff0c;按照行分隔。 垂直分片&#xff1a;一个数据库中多个表格A&#xff0c;B&#xff0c;C&#xff0c;A存储到节点1上&#xff0c;B存储到节点2上&#xff0c;C存储到…

Unity 过场工具(Cutscene)设计(二)

Unity 过场工具(Cutscene)设计&#xff08;二&#xff09; 本章主要分析一下过场一般的必要组成元素&#xff0c;以及在Unity中的制作方案 镜头 通常来说一个表现要求比较高的过场&#xff0c;需要专业的导演进行运镜操作的。 在Unity中官方有一个很好的镜头插件 Cinemachine…

基于Leaflet的VideoOverlay视频图层叠加实战

前言在基于二维的场景中&#xff0c;也许会遇到以下的需求。在某交通路口或者重要的监控点&#xff0c;需要将实时或者录制的视频信息叠加在地图上。更有甚者&#xff0c;随着设备通讯方式的增强&#xff0c;无人机等设备可以采集实时数据&#xff0c;实时回传到控制终端&#…

纵有疾风起,Petterp与他的2022

引言 每逢年末&#xff0c;都要来聊一聊关于今年的各种事情&#xff0c;今昔也不例外:) 与往年不同的是&#xff0c;今天刚搬完家&#xff0c;现在是晚上 1:44 ,正是忙碌一天后比较头痛的时刻。 此刻写点东西&#xff0c;脑子也许会放松一下。&#x1f916; 坐在桌子前&…

RFID技术应用在服装门店管理

服装行业是一个高度一体化的行业&#xff0c;集设计研发、成衣生产、运输、销售于一体。在这些过程中&#xff0c;传统的服装供应链往往消耗巨大的人力、物力和资金成本&#xff0c;但效果一般。当今市场消费者的需求变幻莫测&#xff0c;时尚潮流日新月异。稍有延误&#xff0…

从零编写MDK的FLM烧录算法

文章目录前言一、将代码中的图片资源下载到外部flash1. 修改分散加载文件2. 添加外部flash算法二、制作FLM文件步骤三、使用STM32CubeMX新建工程前言 上文讲过&#xff0c;当我们要下载编译好的镜像到Flash时&#xff0c;首先要做的一步就是选择合适的Flash下载算法&#xff0…

WPS Office 2019 版本 excel透视图创建及删除

摘要&#xff1a;记录一下在做2022年总结数据时遇到的问题&#xff0c;主要问题有2个&#xff0c;①从飞书多维表格导下来数据后不能求和计算和下拉序号&#xff0c;②excel数据透视表创建及删除。 相关文章&#xff1a; 一、Excel WPS Office 2019 版本 excel透视图创建及删…

合作升级|Kyligence 跬智智能分析平台入选华为云联营商品

近日&#xff0c;Kyligence 跬智智能分析平台正式入选华为云联营商品&#xff0c;成为华为云在数据分析领域的联营合作伙伴。通过联营模式&#xff0c;双方将加深在产品、解决方案等多个领域的合作&#xff0c;携手打造“共生、共创、共营、共赢”的合作生态&#xff0c;为用户…

[激光原理与应用-65]:激光器-器件 - 多模光纤(宽频光纤)、单模光纤的原理与区别

第1章 光纤基础与概述1.1 概述光纤是光导纤维的简写&#xff0c;是一种由玻璃或塑料制成的纤维&#xff0c;可作为光传导工具。传输原理是“光的全反射”。微细的光纤封装在塑料护套中&#xff0c;使得它能够弯曲而不至于断裂。通常&#xff0c;光纤的一端的发射装置使用发光二…

Spring Boot(五十三):SpringBoot Actuator之简单实现

1 场景介绍 对于一个大型的几十个、几百个微服务构成的微服务架构系统&#xff0c;在线上时通常会遇到下面一些问题&#xff0c;比如&#xff1a; 1. 如何知道哪些服务除了问题&#xff0c;如何快速定位&#xff1f; (健康状况&#xff09; 2. 如何统一监控各个微服务的性能指标…

不确定性量化 (UQ) 可以显著提高预测准确性,在不确定的世界中获得最佳结果昆士兰大学Mike McKerns-中国学者网

在不确定的世界中获得最佳结果,不确定性量化可以解开成功与失败之间的区别。不确定性量化 &#xff08;UQ&#xff09; 可以显著提高预测准确性&#xff0c;提供设计优化&#xff0c;并在充满未知的世界中促进快速解决方案改进。昆士兰大学的一个机构"不确定性量化基金会&…

vue3中常用的指令之v-bind和v-on

一、v-bind指令 一个vue2和vue3之间的不同之处&#xff1a;Vue2中template模板中只能有一个根元素&#xff0c;但是在Vue3中允许template中有多个元素。 1.v-bind的绑定基本属性 某些属性也希望是动态绑定的&#xff0c;比如动态绑定a元素中的href属性。 v-bind可以绑定一个…

verilog学习笔记- 14)静态数码管显示实验

目录 简介: 实验任务: 硬件设计: 程序设计: 下载验证: 简介: 数码管也称半导体数码管&#xff0c;它是将若干发光二极管按一定图形排列并封装在一起的一种数码显示器件。常见的数码管如图这种数码管主要被称为八段数码管或 8 字形数码管&#xff0c;可用来显示小数点、数…

【Linux 基础】

【Linux 基础】 一、 Linux 概述 1. Linux 介绍 UNIX 是一个强大的多用户、多任务操作系统&#xff0c;于1969年在贝尔实验室开发&#xff0c;UNIX 的商标权有国际开放组织&#xff08;The Open Group&#xff09;所拥有&#xff0c;UNIX 操作系统是商业版&#xff0c;需要收…

【OpenGL学习】Shader和Shader类的抽象

Shader 本节学习OpenGL中Shader的使用并将其抽象为类&#xff0c;简要介绍OpenGL所使用的着色器语言GLSL。 一、什么是Shader&#xff1f; 参考维基百科中对Shader的定义&#xff1a;着色器 - 维基百科&#xff0c;自由的百科全书 (wikipedia.org) 计算机图形学领域中&…

SpringBoot处理跨域总结

解决跨域的五种方法1、CorsFilter新建一个类Configuration public class CorsConfig {Beanpublic CorsFilter corsFilter() {//1. 添加 CORS配置信息CorsConfiguration config new CorsConfiguration();//放行哪些原始域//springboot版本为2.4.0以前写法config.addAllowedOrig…