Mybatis自定义typeHandle过程解析

一 前言

本篇文章的基础是建立在mybatis配置

二 准备工作

2.1建表语句

CREATE TABLE `customer` (
 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
 `customer_name` varchar(255) DEFAULT NULL COMMENT '顾客名称',
 `gender` varchar(255) DEFAULT NULL COMMENT '性别',
 `telephone` varchar(255) DEFAULT NULL COMMENT '电话号码',
 `register_time` timestamp NULL DEFAULT NULL COMMENT '注册时间',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='顾客表';

2.2 实体

public class Customer {
  // 主键
  private Long id;
  // 客户姓名
  private String customer_name;
  // 性别
  private String gender;
  // 电话
  private String telephone;
  // 注册时间
  private Long register_time;
  // 省略 set get
 } 

三 自定义TypeHandler

自定义TypeHandler实现一个业务逻辑就是 当插入数据时可以将时间戳转为timestamp格式;当查询数据得时候再将数据库中得timestamp格式时间转为时间戳;好吧知识追寻者也是无聊透顶了做这种操作,不过易于读者理解;

/**
 * @Author lsc
 * <p> 一个无聊的业务逻辑 输入的是时间戳,到数据库中的是 timestamp 格式 输出的又是时间戳 </p>
 */
@MappedJdbcTypes(JdbcType.TIMESTAMP)
@MappedTypes(Long.class)
public class TimeStringHandler<T> extends BaseTypeHandler<T> {

  public void setNonNullParameter(PreparedStatement preparedStatement, int i, T t, JdbcType jdbcType) throws SQLException {
    // 将 时间戳转为 LocalDateTime
    LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond((java.lang.Long) t), ZoneOffset.ofHours(8));
    // 参数设置
    System.out.println("业务逻辑1");
    preparedStatement.setString(i,localDateTime.toString());
  }

  public T getNullableResult(ResultSet resultSet, String s) throws SQLException {
    System.out.println("业务逻辑2");
    String time = resultSet.getString(s);
    LocalDateTime localDateTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    Long second = localDateTime.toEpochSecond(ZoneOffset.ofHours(8));
    return (T) second;
  }

  public T getNullableResult(ResultSet resultSet, int i) throws SQLException {
    System.out.println("业务逻辑3");
    String time = resultSet.getString(i);
    LocalDateTime localDateTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    Long second = localDateTime.toEpochSecond(ZoneOffset.ofHours(8));
    return (T) second;
  }

  public T getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
    System.out.println("业务逻辑4");
    String time = callableStatement.getString(i);
    LocalDateTime localDateTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    Long second = localDateTime.toEpochSecond(ZoneOffset.ofHours(8));
    return (T) second;
  }
}

四 mappe接口

public interface CustomerMapper {

  // 添加客户
  int addCustomer(Customer customer);
  // 查询客户
  List<Customer> getCustomer();
}

五 sql映射文件

sql映射文件中在使用得字段register_time中做专门得数据类型处理,这样不用配置到全局配置文件中,可以针对特定字段处理是个不错得选择;这边实现得逻辑是两个部分,查询语句用于返回时将register_time使用类型处理器处理;插入语句用于将数据进入数据库时使用register_time使用类型处理器处理。

<?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">

<mapper namespace="com.zszxz.typehandler.mapper.CustomerMapper">

  <resultMap id="customerMap" type="customer" autoMapping="true">
    <result column="register_time" property="register_time" typeHandler="com.zszxz.typehandler.handler.TimeStringHandler"></result>
  </resultMap>

  <select id="getCustomer" resultMap="customerMap" >
    select * from `customer`
  </select>

  <insert id="addCustomer" parameterType="customer">
     insert into `customer`(
      `customer_name`,
      `gender`,
      `telephone`,
      `register_time`
     )values (
      #{customer_name},
      #{gender},
      #{telephone},
      #{register_time,javaType=Long,jdbcType=TIMESTAMP,typeHandler=com.zszxz.typehandler.handler.TimeStringHandler}
     )
  </insert>
</mapper>

六测试类

测试类 也是分为2部分,查询和新增部分;

/**
 * @Author lsc
 * <p> </p>
 */
@RunWith(JUnit4.class)
public class TypeHandlerTest {

  SqlSession sqlSession = null;

  // @Before 会在执行测试类之前执行该方法
  @Before
  public void before() throws IOException {
    // 资源路径 resource目录下
    String resource = "mybatis-config.xml";
    // 配置mybatis获得输入流
    InputStream inputStream = Resources.getResourceAsStream(resource);
    // 创建 SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //从 SqlSessionFactory 中获取 SqlSession
    sqlSession= sqlSessionFactory.openSession();
  }

  @Test
  public void testInsert(){
    // 获得mapper的形式
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
    Customer customer = new Customer();
    customer.setCustomer_name("知识追寻者");
    customer.setRegister_time(1580739214L);
    customer.setGender("男");
    customer.setTelephone("999");
    // 添加客户
    mapper.addCustomer(customer);
    sqlSession.commit();
    sqlSession.close();
  }

  @Test
  public void testSelect(){
    // 获得mapper的形式
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
    List<Customer> customerList = mapper.getCustomer();
    for (Customer customer :customerList){
      System.out.println(customer.getCustomer_name());
      System.out.println(customer.getRegister_time());
    }
    sqlSession.commit();
    sqlSession.close();
  }
}

七 测试插入数据

插入数据时原本register_time是时间戳,从打印得SQL参数2020-02-03T22:13:34(String)可以看见入库时就变成了timestamp支持的格式入库;

[DEBUG] 2020-02-03 23:39:33,018 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Preparing: insert into `customer`( `customer_name`, `gender`, `telephone`, `register_time` )values ( ?, ?, ?, ? )
业务逻辑1
[DEBUG] 2020-02-03 23:39:33,052 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Parameters: 知识追寻者(String), 男(String), 999(String), 2020-02-03T22:13:34(String)
[DEBUG] 2020-02-03 23:39:33,116 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
<== Updates: 1

八 测试查询数据

原本数据库中是timestamp支持的格式得时间,出来就是时间戳;

[DEBUG] 2020-02-03 23:39:00,371 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Preparing: select * from `customer`
[DEBUG] 2020-02-03 23:39:00,410 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Parameters:
业务逻辑2
[DEBUG] 2020-02-03 23:39:00,468 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
<== Total: 1
知识追寻者
1580739214

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Mybatis中自定义TypeHandler处理枚举详解

    在Mybatis中,处理枚举类的TypeHandler有两个: EnumTypeHandler: 用于保存枚举名 EnumOrdinalTypeHandler: 用于保存枚举的序号. 在实际项目中,以上往往不能满足我们的需求. 需求分析 枚举需要包含两个属性,label(用于显示), value(实际的枚举值).数据库保存枚举值(value). 这很明显Mybatis提供的两个枚举TypeHandler不能满足我们的需求.此时,我们可以自定义一个通用的枚举TypeHandler来满足我们的需求.

  • Mybatis自定义TypeHandler解决特殊类型转换问题详解

    我们知道,Java和MySQL中的数据类型是不同的,Java中除了基本数据类型,还有对象. 有时候使用MySQL存储数据,或者从MySQL中读取数据时,会有一些特殊需求 weary ,比如: 将Integer数组直接存入MySQL,保存为BLOB形式,读取出来时又是正常的Integer数组 将Integer数组转换为String,然后存入MySQL,使用varchar类型,读取出来时又是正常的Integer数组 这也太难了叭! 解决办法有两种: Basic Method:Java在存入数据之前,

  • Mybatis实现自定义的typehandler三步曲

    第一步实现接口TypeHandler<T> @MappedJdbcTypes(JdbcType.TIMESTAMP)//此处如果不使用该注解,在myabtis-config.xml中注册该typehandler的时候需要写明jdbctype="TIMESTAMP" @MappedTypes(DateTime.class)//此处如果不使用该注解,在myabtis-config.xml中注册该typehandler的时候需要写明javatype="com.sinos

  • MyBatis自定义typeHandler的完整实例

    自定义typeHandler 对于自定义typeHandler来说,需要在配置文件中注册typeHandlers 然后需要实现TypeHandler接口, 一个例子 首先编写调度的处理类 package com.ming.MyBatis; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import org.apache.logging.log4j.LogManager; imp

  • MyBatis使用自定义TypeHandler转换类型的实现方法

    MyBatis虽然有很好的SQL执行性能,但毕竟不是完整的ORM框架,不同的数据库之间SQL执行还是有差异. 笔者最近在升级 Oracle 驱动至 ojdbc 7 ,就发现了处理DATE类型存在问题.还好MyBatis提供了使用自定义TypeHandler转换类型的功能. 本文介绍如下使用 TypeHandler 实现日期类型的转换. 问题背景 项目中有如下的字段,是采用的DATE类型: birthday = #{birthday, jdbcType=DATE}, 在更新 Oracle 驱动之前

  • mybatis自定义类型处理器TypehHandler示例详解

    前言 当大家使用mybatis作为持久层框架时,在存储和查询数据时,只需要在mapper.xml文件中配置好对应字段的JdbcType和JavaType,mybatis就可以帮我们转化对应的类型.这背后是有mybatis内置的类型转换器做转换(可见源码TypeHandlerRegistry).但是有时候,我们会对某些字段做特殊处理,比如加密和解密.状态转换.类型转换等.这个时候我们需要自定义类型转换器. 类架构 从上面的图中可以看出MyBatis中整个类型处理器实现架构,TypeHandler接

  • Mybatis实战之TypeHandler高级进阶

    上篇文章分享了在项目实战中自定义Mybatis的TypeHandler来处理枚举类型.文章结尾也指出了美中不足之处,那就是每次都需要指定我们自定义的枚举TypeHandler. 随着项目枚举类型的增多,每次都要写一遍这个会令人很反感.那么,本次我们就来解决这一痛点. 思路分析 上篇文章讲到, mybatis有默认的处理枚举类型的TypeHandler,因此,我们要将我们自定义的枚举TypeHandler注册进入Mybatis. 注册完我们自定义的TypeHandler后,还得告诉Mybatis只

  • Mybatis实现自定义类型转换器TypeHandler的方法

    先给大家简单介绍下mybatis MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 此文其实是java操作Oracle类型XMLType总结二:使用Mybatis附带的一篇小结. Mybatis实现自定义的转换器,

  • Mybatis自定义typeHandle过程解析

    一 前言 本篇文章的基础是建立在mybatis配置 二 准备工作 2.1建表语句 CREATE TABLE `customer` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `customer_name` varchar(255) DEFAULT NULL COMMENT '顾客名称', `gender` varchar(255) DEFAULT NULL COMMENT '性别', `telephone` varchar(255)

  • SpringBoot整合mybatis简单案例过程解析

    这篇文章主要介绍了SpringBoot整合mybatis简单案例过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.在springboot项目中的pom.xml中添加mybatis的依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifac

  • python导入不同目录下的自定义模块过程解析

    这篇文章主要介绍了python导入不同目录下的自定义模块过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.代码目录结构 自定义的模块在Common包下,Study文件下SelectionSort.py文件导入自定义的模块 二.源码 2.1:SelectionSort.py文件 python导包默认是从sys.path中搜索的. sys.path结果如下:['D:\\PyCharm\\source\\Study', 'D:\\PyCha

  • Android自定义View过程解析

    Android自定义的view,主要是继承view,然后实现ondraw这个方法,来进行绘制. 1. 编写自己的自定义view 2. 加入逻辑线程 3. 提取和封装自定义view 4. 利用xml中定义样式来影响显示效果 一.编写自定义的view 1.在xml中使用自己的view <!-- 可以使用view的公共属性,例如背景 --> <com.niuli.view.MyView android:layout_width="match_parent" android:

  • SpringBoot自定义FailureAnalyzer过程解析

    这篇文章主要介绍了SpringBoot自定义FailureAnalyzer,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 官网说明 1.1 创建自己的 FailureAnalyzer FailureAnalyzer是一种在启动时拦截 exception 并将其转换为 human-readable 消息的好方法,包含在故障分析中. Spring Boot 为 application context 相关的 exceptions,JSR-303 验

  • springboot自定义Starter过程解析

    自定义Starter命名规则 注意artifactId的命名规则,Spring官方Starter通常命名为spring-boot-starter-{name}如 spring-boot-starter-web, Spring官方建议非官方Starter命名应遵循{name}-spring-boot-starter的格式, 如mybatis-spring-boot-starter.这里创建的项目的artifactId为helloworld-spring-boot-starter 开发Starter

  • Java框架MyBatis接口编程过程解析

    要求: 1.配置文件的namespace名称空间指定为接口的全类名 2.配置文件中的id唯一标识与接口中的方法对应(返回值类型对应,方法名对应,参数个数和类型对应) 接口代码: package com.bird.mybatis.dao; import com.bird.mybatis.bean.Employee; public interface EmployeeMapper { public Employee getEmpById(Integer id); } 对应配置文件代码: <?xml

  • Nginx服务器添加Systemd自定义服务过程解析

    一.以nginx为例 使用yum命令安装的nginx Systemd服务文件以.service结尾,比如现在要建立nginx为开机启动,如果用yum install命令安装的,yum命令会自动创建nginx.service文件,直接用命令: systemcel enable nginx.service //开机自启 使用源码编译安装的 1.手动创建nginx.service服务文件.并将其放入 /lib/systemd/system 文件夹中. nginx.service内容如下: [Unit]

  • SpringBoot整合Junit实例过程解析

    这篇文章主要介绍了SpringBoot整合Junit实例过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前提条件:SpringBoot已经整合了Mybatis,至于SpringBoot如何整合Mybatis可参考SpringBoot整合mybatis简单案例过程解析 SpringBoot为什么要整合Juni? SpringBoot整合了Junit后,在写了Mapper接口后,可直接通过Junit进行测试,不用再写Controller层,

  • mybatis plus代码生成器配置过程解析

    这篇文章主要介绍了mybatis plus代码生成器配置过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 最近在玩项目,发现自己写严重浪费时间~于是想到了代码生成器,之前用过一次的mybatis-plus,再重新实现了一下 确保修改好对应的配置即可 依赖: <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boo

随机推荐