User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • Enamiĝu al vi
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • 666资源站
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
Help?

Please contact us on our email for need any support

Support
    首页   ›   SQL   ›   MyBatis   ›   正文
MyBatis

MyBatis笔记8—typeHandlers

2020-03-20 00:43:15
661  0 1

阅读完需:约 9 分钟

typeHandlers又叫类型处理器,就像在JDBC中,我们在PreparedStatement中设置预编译sql所需的参数或执行sql后根据结果集ResultSet对象获取得到的数据时,需要将数据库中的类型和java中字段的类型进行转换一样,在MyBatis中使用typeHandler来实现。

所以说白了,typeHandlers就是用来完成javaType和jdbcType之间的转换。

举个比较简单的例子,我创建一个博客表,表中的创建时间和修改时间用VARCHAR类型,但是在我的POJO对象中,创建时间和修改时间的类型是Date,这样我在向数据库插入数据时,需要将日期类型转化成VARCHAR,而从数据库中查询出的结果中,又需要将VARCHAR类型转换成Date.在MyBatis中,使用typeHandlers配置来实现这个转换过程。

MyBatis会根据javaType和jdbcType来决定采用哪个typeHandler来处理这些转换规则,而且系统定义的能满足大部分需求,可以说是非常好用,用户只需要自定义一些特有的转换规则。

在 MyBatis 映射中,能够自动将 Jdbc 类型映射为 Java 类型。默认的映射规则,如下:

类型处理器Java类型JDBC类型
BooleanTypeHandlerBoolean,boolean任何兼容的布尔值
ByteTypeHandlerByte,byte任何兼容的数字或字节类型
ShortTypeHandlerShort,short任何兼容的数字或短整型
IntegerTypeHandlerInteger,int任何兼容的数字和整型
LongTypeHandlerLong,long任何兼容的数字或长整型
FloatTypeHandlerFloat,float任何兼容的数字或单精度浮点型
DoubleTypeHandlerDouble,double任何兼容的数字或双精度浮点型
BigDecimalTypeHandlerBigDecimal任何兼容的数字或十进制小数类型
StringTypeHandlerStringCHAR和VARCHAR类型
ClobTypeHandlerStringCLOB和LONGVARCHAR类型
NStringTypeHandlerStringNVARCHAR和NCHAR类型
NClobTypeHandlerStringNCLOB类型
ByteArrayTypeHandlerbyte[]任何兼容的字节流类型
BlobTypeHandlerbyte[]BLOB和LONGVARBINARY类型
DateTypeHandlerDate(java.util)TIMESTAMP类型
DateOnlyTypeHandlerDate(java.util)DATE类型
TimeOnlyTypeHandlerDate(java.util)TIME类型
SqlTimestampTypeHandlerTimestamp(java.sql)TIMESTAMP类型
SqlDateTypeHandlerDate(java.sql)DATE类型
SqlTimeTypeHandlerTime(java.sql)TIME类型
ObjectTypeHandler任意其他或未指定类型
EnumTypeHandlerEnumeration类型VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。

前面案例中,之所以数据能够接收成功,是因为有上面这些默认的类型处理器,处理基本数据类型,这些够用了,特殊类型,需要我们自定义类型处理器。

比如,我有一个用户爱好的字段,这个字段,在对象中,是一个 List 集合,在数据库中,是一个 VARCHAR 字段,这种情况下,就需要我们自定义类型转换器,自定义的类型转换器提供两个功能:

  1. 数据存储时,自动将 List 集合,转为字符串(格式自定义)
  2. 数据查询时,将查到的字符串再转为 List 集合

首先,在数据表中添加一个 favorites 字段

然后,在 User 对象中,添加相应的属性:

public class User {
    private Integer id;
    private String username;
    private String address;
    private List<String> favorites;

    public List<String> getFavorites() {
        return favorites;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", address='" + address + '\'' +
                ", favorites=" + favorites +
                '}';
    }

    public void setFavorites(List<String> favorites) {
        this.favorites = favorites;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

为了能够将 List 集合中的数据存入到 VARCHAR 中,我们需要自定义一个类型转换器:

@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class List2VarcharHandler implements TypeHandler<List<String>> {
    public void setParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
        StringBuffer sb = new StringBuffer();
        for (String s : parameter) {
            sb.append(s).append(",");
        }
        ps.setString(i, sb.toString());
    }

    public List<String> getResult(ResultSet rs, String columnName) throws SQLException {
        String favs = rs.getString(columnName);
        if (favs != null) {
            return Arrays.asList(favs.split(","));
        }
        return null;
    }

    public List<String> getResult(ResultSet rs, int columnIndex) throws SQLException {
        String favs = rs.getString(columnIndex);
        if (favs != null) {
            return Arrays.asList(favs.split(","));
        }
        return null;
    }

    public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String favs = cs.getString(columnIndex);
        if (favs != null) {
            return Arrays.asList(favs.split(","));
        }
        return null;
    }
}
  • 首先在这个自定义的类型转换器上添加 @MappedJdbcTypes 注解指定要处理的 Jdbc 数据类型,另外还有一个注解是 @MappedTypes 指定要处理的 Java 类型,这两个注解结合起来,就可以锁定要处理的字段是 favorites 了。
  • setParameter 方法看名字就知道是设置参数的,这个设置过程由我们手动实现,我们在这里,将 List 集合中的每一项,用一个 , 串起来,组成一个字符串。
  • getResult 方法,有三个重载方法,其实都是处理查询的。

接下来,修改插入的 Mapper:

<insert id="addUser" parameterType="org.javaboy.mybatis.model.User">
    insert into user (username,address,favorites) values (#{username},#{address},#{favorites,typeHandler=org.javaboy.mybatis.typehandler.List2VarcharHandler});
</insert>

然后,在 Java 代码中,调用该方法:

public class Main2 {
    public static void main(String[] args) {
        SqlSessionFactory instance = SqlSessionFactoryUtils.getInstance();
        SqlSession sqlSession = instance.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUsername("风气");
        user.setAddress("上海");
        List<String> favorites = new ArrayList<String>();
        favorites.add("足球");
        favorites.add("篮球");
        favorites.add("乒乓球");
        user.setFavorites(favorites);
        mapper.addUser(user);
        sqlSession.commit();
    }
}

这样,List 集合存入到数据库中之后,就变成一个字符串了

读取的配置,有两个地方,一个可以在 ResultMap 中做局部配置,也可以在全局配置中进行过配置,全局配置方式如下:

<configuration>
    <properties resource="db.properties"></properties>
    <typeAliases>
        <package name="org.javaboy.mybatis.model"/>
    </typeAliases>
    <typeHandlers>
        <package name="org.javaboy.mybatis.typehandler"/>
    </typeHandlers>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${db.driver}"/>
                <property name="url" value="${db.url}"/>
                <property name="username" value="${db.username}"/>
                <property name="password" value="${db.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="org.javaboy.mybatis.mapper"/>
    </mappers>
</configuration>

接下来去查询,查询过程中,就会自动将字符串转为 List 集合了。


ArrayTypeHandler 与 JsonTypeHandler

处理数组类型及使用Json格式保存数据 JsonTypeHandler and ArrayTypeHandler

建一张表:

create table user (

  id serial not null

  name character varchar(100),

  age integer,

  emails character varchar[],  -- varchar 数组 表示可以多个email

  address character varchar(2000) -- 因为地址内容为非结构化的数据,我们希望保存json格式描述的地址信息,以增加灵活性

);

这个表有2个字段值得我们注意:

  1. emails 为 character varchar[] 数组类型
  2. address 我们希望保存为json格式的数据,查询时返回json字符串,mybatis orm 之后可以还原为一个数据对象VO。

完成这2个需求,则需要我们标题中提到的 JsonTypeHandler & ArrayTypeHandler

先看第一个typHandler: ArrayTypeHandler

public class UserVO {

    private long id;
    private String name;
    private int age;
    private String[] emails;
    Private Object address;

    ......
}

其中 emails 对应数据库的 emails,address 对应数据库的 address,为什么用Object类型呢,这是因为以后我们可能会有个 AddressVO 这样的对象,也可能会有 AddressVO2 extends AddressVO 这样的对象,但是数据库的schame不会变。

接下来我们看一下 UserDao.xml 中的片段:

<resultMap type="com.kylin.test.userVO" id="userVO">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <result property="age" column="age"/>
    <result property="emails" column="emails" typeHandler="org.apache.ibatis.type.ArrayTypeHandler"/>
    <result property="address" column="address" typeHandler="org.apache.ibatis.type.JsonTypeHandler"/>
</resultMap>

上面的resultMap中配置了2个typeHandler,关于typeHandler的配置,mybatis有多种方法,这里简单示意一下。

<insert id="addUser" parameterType="com.kylin.test.UserVO">    
    INSERT INTO user (
        name, 
        age, 
        emails, 
        address)
    VALUES (
        #{name, jdbcType=VARCHAR},
        #{age, jdbcType=INTEGER},
        #{emails, jdbcType=ARRAY, typeHandler=org.apache.ibatis.type.ArrayTypeHandler},
        #{address, jdbcType=VARCHAR, typeHandler=org.apache.ibatis.type.JsonTypeHandler})
</insert>

<select id="getUserById" resultMap="userVO">
    SELECT * 
    FROM user
    WHERE id = #{0}
</select>

上述的addUser方法,传入了字符串数组,和Object对象,保存到了数据库中,见下面的代码:

UserVO user = new UserVO();

    user.setName("kylin");
    user.setAge(30);
    user.setEmails(new String[] { "kylin@163.com", "kylin@263.com" });

    Map<String, Object> address = new HashMap<String, Object>();
    address.put("country", "china");
    address.put("province", "guangdong");
    address.put("city", "shenzhen");
    user.setAddress(address);

    // 调用dao.addUser方法
    userDao.addUser(user);

上面这个方法,将emails 字符串数组保存入数据库,将Map address,以json字符串的方式保存到数据库

select * from user;

id name     age   emails                                               address
-------------------------------------------------------------------------------
 1 kylin        30   ["kylin@163.com","kylin@126.com"]  {"contry":"china","province":"guangdong","city":"shenzhen"}

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

1 打赏
Enamiĝu al vi
一个人若有一百只羊,一只走迷了路,你们的意思如何?他岂不撇下这九十九只,往山里去找那只迷路的羊吗?
519文章 67评论 191点赞 323884浏览

默认版本~SpringBoot2.0~2.3
  • Java—定时任务—HashedWheelTimer时间轮
  • Java—有向无环图(DAG)
  • JXLS—Excel模板框架
  • Disruptor—无锁队列
  • Redis—注解接口限流
  • SpringBoot—数据库读写分离
  • Netty—初探与核心(未完)
随便看看
ActiveMQ (4) Ajax (13) Docker (7) ElasticSearch (13) Enamiĝu al vi (1) Eureka (2) Feign (6) Freemarker (5) Gateway (6) Git (5) Hystrix (7) Java (78) Java Notes (117) JavaScript (1) jQuery (2) Kotlin Notes (47) Maven (2) More (2) MyBatis (42) MySQL (5) Netty (2) NOSQL (1) OAuth2 (11) PostgreSQL (4) RabbitMQ (6) Redis (18) Ribbon (6) Servlet (3) Spring (70) SpringBoot (85) SpringCloud (14) SpringJPA (4) SpringMVC (46) Spring Notes (43) SpringSecurity (49) SQL (15) SQL Notes (9) SQL Server (2) Thymeleaf (4) Vue (9) Web (12) Web Notes (18) WebSocket (9) XML (1) Zuul (3)
随便看看
  • 2023年5月 (2)
  • 2023年4月 (1)
  • 2023年3月 (1)
  • 2023年2月 (5)
  • 2023年1月 (4)
  • 2022年12月 (1)
  • 2022年11月 (3)
  • 2022年10月 (5)
  • 2022年9月 (8)
  • 2022年8月 (1)
  • 2022年7月 (2)
  • 2022年6月 (4)
  • 2022年5月 (5)
  • 2022年4月 (3)
  • 2022年3月 (7)
  • 2022年2月 (4)
  • 2022年1月 (15)
  • 2021年12月 (16)
  • 2021年11月 (3)
  • 2021年10月 (3)
  • 2021年9月 (3)
  • 2021年8月 (2)
  • 2021年7月 (4)
  • 2021年6月 (16)
  • 2021年5月 (3)
  • 2021年4月 (2)
  • 2021年3月 (13)
  • 2021年2月 (2)
  • 2021年1月 (33)
  • 2020年12月 (13)
  • 2020年11月 (6)
  • 2020年10月 (17)
  • 2020年9月 (26)
  • 2020年8月 (46)
  • 2020年7月 (28)
  • 2020年6月 (4)
  • 2020年5月 (16)
  • 2020年4月 (88)
  • 2020年3月 (104)
随机文章
SpringMVC笔记15—RESTful
3年前
Spring—RestTemplate的使用和原理
3年前
MyBatis笔记10—resultType(返回类型)
3年前
Java—并发编程(七)JUC集合 – (9) LinkedBlockingDeque
1年前
Freemarker的相关配置
3年前
整合SSM框架
3年前
ENMAL摘要

1、Kotlin:

https://www.liuwj.me/

 

2、webflux:

https://www.cnblogs.com/lixinjie/p/a-brother-of-spring-mvc-is-spring-webflux.html

 

3、Java中的Unsafe

 

4、https://my.oschina.net/quanke/blog/1631990

 

5、https://blog.csdn.net/u013064109/article/details/78786646?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522161214257916780264022540%252522%25252C%252522scm%252522%25253A%25252220140713.130102334.pc%25255Fall.%252522%25257D&request_id=161214257916780264022540&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-11-78786646.first_rank_v2_pc_rank_v29&utm_term=kotlin

 

6、待学习除Spring之外的Web框架 — Cloudopt Next、Javalin、jfinal

https://jfinal.com/doc

 

7、kotlin设计模式——https://github.com/AboutKotlin/Design-Patterns-In-Kotlin

 

8、kotlin–ktorm+SpringBoot——https://gitee.com/tianchaohongyu/Spring-Boot-Ktor-Starter

 

9、新技术 — CQRS、jasync-sql、play!framework、akka、asyncdb

 

10、Kotlin Tips

https://gitee.com/lesliekoma/kotlin_tips?_from=gitee_search#tip5–%E6%87%92%E5%88%9D%E5%A7%8B%E5%8C%96by-lazy-%E5%92%8C-%E5%BB%B6%E8%BF%9F%E5%88%9D%E5%A7%8B%E5%8C%96lateinit

 

11、mall项目电商系统

https://github.com/macrozheng/mall

 

12、POI大量读写

https://www.cnblogs.com/swordfall/p/8298386.html

 

13、Gitee

权限RBAC:

https://gitee.com/log4j/pig

 

14、freecodecamp、pf4j

 

15、https://javadoop.com/

 

16、https://www.cnblogs.com/skywang12345/

 

17、Flyway

 

18、https://github.com/kotlin-orm/ktorm/pull/296

 

kt实体类自动生成表

 

https://github.com/tursom/TursomServer/tree/master/ts-database/src/main/kotlin/cn/tursom/database

 

19、蓝狐、支付沙盒、虚拟币

 

20、r2dbc spring强推,vertx这边是quarkus强推 redhat认证

 

21、Keycloak为Web应用和Restful服务提供了一站式的单点登录解决方案。

 

22、RSQL 的形式为 Restful API 带来了 SQL 声明性的便利

https://github.com/vineey/archelix-rsql

https://github.com/ymind/rsql-ktorm

 

23、Kotlin依赖注入

https://github.com/InsertKoinIO/koin

 

24、Kotlin– Alpas

https://github.com/alpas/alpas

一个基于 Kotlin 的 Web 框架,可让您简单快速地创建 Web 应用程序和 API。

 

25、外网学习网站,文章

https://medium.com/nerd-for-tech

 

26、Compose Multiplatform 进入 Alpha 版,统一桌面、Web 和 Android UI

https://blog.jetbrains.com/kotlin/2021/08/compose-multiplatform-goes- alpha/

 

27、Sureness

面向REST API的高性能认证鉴权框架,致力于管理保护API安全

https://gitee.com/dromara/sureness

与Javalin结合

https://javalin.io/2021/04/16/javalin-sureness-example.html

 

28、Kotlin官网合集库

https://kotlinlang.org/lp/server-side/

https://kotlinlang.org/lp/server-side/

https://kotlinlang.org/lp/server-side/

 

29、CLI知识体系

https://juejin.cn/post/6966119324478079007

 

30、面向 Web、移动和 Flutter 开发人员的安全开源后端服务器

https://appwrite.io/

 

31、Java锁

https://blog.csdn.net/hancoder/article/details/120421993

 

32、java—简单的鉴权认证

介绍 – Sa-Token (dev33.cn)

 

33、Effective Kotlin 中文翻译

GitHub – MaxzMeng/Effective-Kotlin-zh-CN: Effective Kotlin 中文翻译

 

34、Nutz—国产Web开源框架

http://www.nutzam.com/core/nutz_preface.html

 

35、Quarkus 夸克—国外开源框架

https://quarkus.io/

 

36、目前6个框架

  1. Spring Reactive → 背靠 Pivotal → 归属 VMware → 归属戴尔
  2. Quarkus 和 Vert.x → 背靠 Eclipse 基金会 → 主要由 Red Hat 支持
  3. Helidon → 背靠 Oracle
  4. Micronaut → 背靠 Object Computing(Grails、OpenDDS)
  5. Lagom → 背靠 Lightbend(Akka)
  6. Ktor → 背靠 JetBrains

 

37、XXL-JOB—–分布式任务调度平台

https://www.xuxueli.com/xxl-job/#%E3%80%8A%E5%88%86%E5%B8%83%E5%BC%8F%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%E5%B9%B3%E5%8F%B0XXL-JOB%E3%80%8B

 

38、领域设计驱动模版

https://myddd.org

 

39、BFF— Backend For Frontend

 

40、面试突击小册

https://snailclimb.gitee.io/javaguide-interview/#/

https://javaguide.cn/

 

41、JeecgBoot 是一款基于代码生成器的低代码开发平台

http://doc.jeecg.com/2043868

 

42、

IdentityServer4 是用于 ASP.NET Core 的 OpenID Connect 和 OAuth 2.0 框架。

https://identityserver4docs.readthedocs.io/zh_CN/latest/index.html

 

43、cn.novelweb 工具类的个人博客

https://blog.novelweb.cn

 

44、分布式链路追踪SkyWalking

 

45、刷题模版

https://blog.csdn.net/fuxuemingzhu/article/details/101900729

 

46、TS中文文档

https://ts.xcatliu.com/

 

47、Rust 中文文档

https://kaisery.github.io/trpl-zh-cn/ch00-00-introduction.html

 

48、Bean Searcher 只读 ORM

https://searcher.ejlchina.com/guide/latest/start.html

 

49、K8S的学习手册

https://kuboard.cn/learning/k8s-basics/kubernetes-basics.html#%E5%AD%A6%E4%B9%A0%E7%9B%AE%E6%A0%87

 

50、fluent-mybatis, mybatis语法增强框架(关键自动生成代码JavaPoet)

https://gitee.com/fluent-mybatis/fluent-mybatis?_from=gitee_search

 

51、程序猿博客

https://qicoder.com/categories/

https://blog.hhui.top/hexblog/

https://fangshixiang.blog.csdn.net/category_7941357_2.html

https://www.zhihu.com/people/zhuo-zi-yang-93

 

52、itxiaoshen大佬的分享

https://www.cnblogs.com/itxiaoshen/

 

53、MySQL实战学习

https://funnylog.gitee.io/mysql45/

 

54、八股文

https://www.javalearn.cn/#/

 

55、两个宣传很牛的IO框架

https://gitee.com/smartboot/smart-socket

https://www.tiocloud.com/doc/taixin/?pageNumber=1

 

56、GIS动态扩散模型

https://43.140.250.235/vue/#/

 

57、PGGIS大佬

https://blog.csdn.net/m0_60387551/article/details/123184049

 

58、有时间看一下的东西

Trino、presto、shenyu、Pigx

 

59、外网IT博客

https://kt.academy/article/dispatcher-loom

https://medium.com/

https://vived.io/blog/page/2/

https://vived.io/blog/page/2/

https://vived.io/blog/page/2/

https://www.bmpi.dev/dev/

 

60、源码阅读笔记

https://github.com/seaswalker/jdk-sourcecode-analysis

https://github.com/doocs/source-code-hunter

 

61、图书下载

http://www.ucdrs.superlib.net/

http://www.chendianrong.com/pdf#g

 

62、组件式规则引擎—liteflow

https://liteflow.yomahub.com/

 

Copyright © 2023 网站备案号: 浙ICP备20017730号
主页
页面
  • 归档
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
519 文章 67 评论 323884 浏览
测试
测试
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付