Ibatis的类型处理器TypeHandler解析
- 格式:docx
- 大小:26.26 KB
- 文档页数:4
mybatis 类型映射原理
MyBatis类型映射原理:
MyBatis是一种流行的持久化框架,它提供了一种简单的方法将数据库中的数据映射到Java对象上。
类型映射是MyBatis中的一个重要概念,它允许我们在数据库和Java之间建立一种对应关系,使数据的读写操作更加方便。
在MyBatis中,类型映射是通过TypeHandler完成的。
TypeHandler负责将数据库中的数据类型转换为Java对象,并将Java对象转换为数据库中的数据类型。
TypeHandler是一个接口,我们可以通过实现该接口来定义自己的类型映射规则。
MyBatis内置了许多常用的TypeHandler,例如IntegerTypeHandler、StringTypeHandler等。
当我们在映射文件或注解中指定某个字段的类型时,MyBatis会自动选择合适的TypeHandler进行类型转换。
此外,MyBatis还提供了注解来简化类型映射的配置。
我们可以通过
@MappedTypes和@MappedJdbcTypes注解来指定Java类型和数据库类型之间的映射关系。
对于复杂的类型映射,MyBatis还支持自定义TypeHandler。
我们可以实现TypeHandler接口,重写其中的方法来完成自定义的类型转换逻辑。
总结起来,MyBatis的类型映射原理就是通过TypeHandler来处理数据库和Java类型之间的转换。
它提供了内置的TypeHandler,并支持自定义TypeHandler 来满足更复杂的类型转换需求。
通过合理配置类型映射,我们可以更方便地操作数据库中的数据。
mybatis⾃定义类型处理器TypehHandler⽰例详解前⾔当⼤家使⽤mybatis作为持久层框架时,在存储和查询数据时,只需要在mapper.xml⽂件中配置好对应字段的JdbcType和JavaType,mybatis就可以帮我们转化对应的类型。
这背后是有mybatis内置的类型转换器做转换(可见源码TypeHandlerRegistry)。
但是有时候,我们会对某些字段做特殊处理,⽐如加密和解密、状态转换、类型转换等。
这个时候我们需要⾃定义类型转换器。
类架构从上⾯的图中可以看出MyBatis中整个类型处理器实现架构,TypeHandler接⼝定义了类型处理器,⽽TypeReference抽象类则定义了⼀个类型引⽤,⽤于引⽤⼀个泛型类型(此处很抽象,不好理解,详见后续解析),BaseTypeHandler则是类型处理器的基础,是所有类型处理器的公共模块,⼏乎所有的类型处理器都是通过直接继承BaseTypeHandler来实现的。
⼀、原理使⽤场景:mybatis在预处理语句(PreparedStatement)中设置⼀个参数时,或者从结果集(ResultSet)中取出⼀个值时,都会⽤到TypeHandler。
它的作⽤就是将java类型(javaType)转化为jdbc类型(jdbcType),或者将jdbc类型(jdbcType)转化为java类型(javaType)。
⼆、⾃定义类型处理器实现TypeHandler接⼝或者继承BaseTypehandlerTypeHandler是⼀个接⼝,它定义了如下四个⽅法,实现类必须去实现,⽅法如下:void setParameter(PreparedStatement var1, int var2, T var3,JdbcType var4) throws SQLException;T getResult(ResultSet var1, String var2) throws SQLException;T getResult(ResultSet var1, int var2) throws SQLException;T getResult(CallableStatement var1, int var2) throws SQLException;}setParameter:通过preparedStatement对象设置参数,将T类型的数据存⼊数据库。
mybatis typehandler运行原理-回复MyBatis是一个流行的Java持久层框架,它提供了方便的数据库访问方式。
在MyBatis中,通过使用TypeHandler来处理Java对象与数据库字段之间的映射关系。
本篇文章将介绍MyBatis TypeHandler的运行原理,并一步一步回答中括号中的问题。
1. TypeHandler概述TypeHandler是MyBatis中一个重要的组件,它负责Java对象和数据库字段之间的类型转换操作。
MyBatis提供了许多预定义的TypeHandler,用于处理各种常见的Java和数据库类型之间的映射关系。
如果需要处理自定义的Java类型或数据库类型,可以编写自己的TypeHandler实现。
2. TypeHandler接口TypeHandler接口是所有TypeHandler实现类的父接口,其中定义了一系列处理Java对象与数据库字段之间映射的方法。
其中最重要的方法是setParameter和getResult,分别用于设置参数值和获取结果值。
3. 数据库类型到Java类型的映射在使用TypeHandler时,MyBatis首先根据数据库字段的类型确定具体使用哪个TypeHandler处理。
MyBatis提供了一系列内置的TypeHandler,每个TypeHandler负责处理一种数据库类型。
内置TypeHandler根据数据库类型的不同,使用不同的Java数据类型进行映射,如Integer、String、BigDecimal等。
4. Java类型到数据库类型的映射当将Java对象保存到数据库中时,MyBatis会根据Java对象的类型使用对应的TypeHandler。
TypeHandler会将Java对象转换为数据库能够接受的类型,然后通过JDBC将数据存储到数据库中。
5. TypeHandler的注册所有的TypeHandler都需要进行注册才能被MyBatis框架识别和使用。
MyBatisPlus⾃动类型转换之TypeHandlerMyBatis Plus ⾃动类型转换之TypeHandler数据库表⾥有ids字段,存放的都是主键id,逗号分隔。
model⾥⾯是Set集合装Integer类型的 ids⽤MyBatis的TypeHandler做⾃动类型转换分三步:1.实体类需要加个注解@TableName(autoResultMap = true)2.对应对象的属性也需要加注解@TableField(typeHandler = SetTypeHandler.class)3.继承BaseTypeHandler实现其⽅法@MappedTypes(Set.class)@MappedJdbcTypes(JdbcType.VARCHAR)public class SetTypeHandler extends BaseTypeHandler<Set> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Set parameter, JdbcType jdbcType)throws SQLException {String param = parameter.toString().replaceAll("\\[|\\]| ", "");ps.setString(i, param);}@Overridepublic Set<Integer> getNullableResult(ResultSet rs, String columnName)throws SQLException {String sqlSet = rs.getString(columnName);return getSet(sqlSet);}@Overridepublic Set<Integer> getNullableResult(ResultSet rs, int columnIndex)throws SQLException {String sqlSet = rs.getString(columnIndex);return getSet(sqlSet);}@Overridepublic Set<Integer> getNullableResult(CallableStatement cs, int columnIndex)throws SQLException {String sqlSet = cs.getString(columnIndex);return getSet(sqlSet);}private Set<Integer> getSet(String sqlSet) {if (StringUtils.isNotBlank(sqlSet)) {return Arrays.asList(sqlSet.split(",")).stream().map(Integer::parseInt).collect(Collectors.toSet());}return new HashSet();}}解释以上代码:实体类要转换的类型:Set@MappedTypes(Set.class)对应数据库表的字段类型:varchar@MappedJdbcTypes(JdbcType.VARCHAR)参数set,⽤来给参数PreparedStatement对象对应的列设置参数,预编译SQL语句,在SQL语句执⾏之前改变语句。
mybatis-plus如何配置⾃定义数据类型TypeHandle⽬录如何配置⾃定义数据类型TypeHandle1.背景2.举例3.TypeHandle配置⾃定义TypeHandler的使⽤笔记类型转换器还可以通过注解配置java类型和jdbc类型如何配置⾃定义数据类型TypeHandle1.背景mybatis-plus在mybatis的基础的上,做了全⾯增强功能,极⼤的提⾼了我们的开发效率。
有时候我们使⽤的实体字段类型,与数据库创建的字段类型⽆法对应上,这时候就需要配之⾃定义的类型处理类,来处理代码和数据库之间的数据流转。
2.举例我们有个实体类TestEntity,使⽤注解@TableName表⽰对应数据库表名为test@Data@TableName(value = "test")public class TestEntity{private static final long serialVersionUID = 8565214506859404278L;private String id;private String type;private Document content;}DAO层对象@Mapperpublic interface TestDao extends BaseMapper<TestEntity> {}XML⽂件<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN" "/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.aisino.dao.TestDao"><resultMap type="com.aisino.entity.TestEntity" id="testMap"><result property="id" column="id"/><result property="type" column="name"/><result property="content" column="content"/></resultMap></mapper>其中Document使⽤的是org.w3c.dom.Document对象,数据库存储的字段类型为bytea,我这⾥使⽤的是postgresql,显然数据类型⽆法匹配,这⾥需要编写类型处理类进⾏数据类型转换。
basetypehandler使用关于basetypehandler的使用方法和功能的文章。
basetypehandler是MyBatis中的一个重要组件,它扮演着类型处理器(TypeHandler)的基础角色,用于处理Java对象与数据库字段类型之间的转换。
本篇文章将以basetypehandler的使用为主题,详细解答如何使用basetypehandler来实现Java对象与数据库字段类型之间的转换,并介绍其特点和优势。
一、什么是basetypehandler?basetypehandler是MyBatis中用于处理Java对象与数据库字段类型之间转换的基本类型处理器。
它属于MyBatis框架自带的类型处理器之一,我们可以直接调用它的API来实现数据类型转换。
basetypehandler支持多种常见数据类型的转换,如字符串、整数、日期等。
二、basetypehandler的使用方法1. 导入项目依赖在使用basetypehandler之前,首先需要在项目的配置文件(如pom.xml)中添加对MyBatis的依赖。
可以在Maven中央仓库搜索并添加MyBatis 相关的依赖,再使用Maven或Gradle进行项目构建。
2. 创建Java对象在代码中定义需要进行类型转换的Java对象。
假设我们有一个User类,其中包含一个age字段:javapublic class User {private int age;省略getter和setter方法}3. 创建TypeHandler接下来我们需要创建一个继承自basetypehandler的自定义类型处理器,用于处理User类中的age字段。
在创建TypeHandler时,需要指定Java 类型和数据库字段类型:javapublic class AgeTypeHandler extends BaseTypeHandler<Integer> { Overridepublic void setNonNullParameter(PreparedStatement preparedStatement, int i, Integer integer, JdbcType jdbcType) throws SQLException {preparedStatement.setInt(i, integer);}Overridepublic Integer getNullableResult(ResultSet resultSet, String s) throws SQLException {return resultSet.getInt(s);}Overridepublic Integer getNullableResult(ResultSet resultSet, int i) throws SQLException {return resultSet.getInt(i);}Overridepublic Integer getNullableResult(CallableStatement callableStatement, int i) throws SQLException {return callableStatement.getInt(i);}}在这个例子中,我们创建了一个AgeTypeHandler类,用于处理Integer 类型的age字段。
java mybatis booleantypehandler 用法全文共四篇示例,供读者参考第一篇示例:Java是一种广泛应用的编程语言,在开发过程中常常会涉及到数据库操作。
MyBatis是一款优秀的持久层框架,可以帮助开发者在Java应用中轻松地进行数据库操作。
在MyBatis中,BooleanTypeHandler是一种非常常用的类型处理器,用于处理boolean类型的数据。
BooleanTypeHandler的作用是将数据库中的boolean类型数据与Java中的boolean类型数据进行转换。
在数据库中,通常使用1或0来表示true或false。
而在Java中,boolean类型的变量只能取true 或false这两个值。
BooleanTypeHandler在这两者之间起到了桥梁的作用,方便开发者对数据的处理。
使用BooleanTypeHandler的方式很简单,只需要在MyBatis的配置文件中进行相应的配置即可。
在数据库表对应的实体类中,需要将boolean类型的字段定义为Boolean类型,而不是基本数据类型boolean。
然后,在MyBatis的配置文件中,添加如下的配置:```xml<typeHandlers><typeHandlerhandler="org.apache.ibatis.type.BooleanTypeHandler" javaType="ng.Boolean"/></typeHandlers>```@Overrideprotected String convertToJdbcType(Boolean aBoolean) {return aBoolean ? "Y" : "N";}}```然后在MyBatis的配置文件中使用这个自定义的类型处理器:通过这种方式,开发者可以自定义类型处理器来处理不同类型的数据转换,使得数据在数据库与Java代码之间的交互更加灵活。
handler的运行机制Handler的运行机制Handler是Android开发中非常重要的一个概念,它在Android 中起到了非常重要的作用,它可以帮助我们实现异步操作,以及主线程和子线程之间的通信。
Handler的运行机制分为三个部分:消息队列、消息处理器和消息。
我们来看看消息队列,消息队列是Handler的核心之一,它是用来保存消息的队列。
当我们向Handler发送消息时,它会将消息存放到队列中,然后由Handler按照一定的规则进行处理。
消息队列中的消息是按照优先级排序的,先进先出,后进后出。
接下来,我们来看看消息处理器,消息处理器是用来处理消息的。
当消息队列中有消息时,Handler会调用它的处理函数来处理消息。
消息处理器会根据消息的类型,执行相应的操作。
比如,当我们使用Handler.post()方法发送一个Runnable对象时,消息处理器会将它存储在消息队列中,并在处理时调用它的run()方法。
我们来看看消息,消息是Handler中的最小单位,它是用来传递信息的。
当我们向Handler发送消息时,我们需要创建一个Message对象,并将它传递给Handler。
Message对象中包含了消息的类型以及一些附加信息。
在Handler的处理函数中,我们可以根据消息的类型来执行相应的操作。
在整个Handler的运行过程中,主线程和子线程之间的通信是非常重要的。
当我们在子线程中执行一些操作时,如果需要更新UI,我们就需要使用Handler来实现。
在主线程中创建Handler对象,并将它传递给子线程,子线程就可以通过Handler来向主线程发送消息,从而更新UI。
总的来说,Handler的运行机制是非常复杂的,但是它的作用是非常重要的。
它可以帮助我们实现异步操作,以及主线程和子线程之间的通信。
在实际的开发中,我们需要熟练掌握Handler的使用,以便更好地开发出高质量的Android应用程序。
mybatis typehandler 处理时间偏移量当我们在使用MyBatis进行数据库操作的时候,经常会遇到处理时间偏移量的情况。
在这种情况下,我们需要使用MyBatis的类型处理器(TypeHandler)来处理时间偏移量的转换。
时间偏移量是指时间相对于标准时区的偏移量,比如东八区的时间偏移量为+8:00,西五区的时间偏移量为-5:00。
在数据库中,时间偏移量通常以字符串的形式存储,例如"+08:00"或"-05:00"。
但是在Java代码中,我们通常会使用Java中的Date或LocalDateTime来表示时间。
这就需要我们在将时间值从数据库中读取出来时,将字符串类型的时间偏移量转换为Java中的Date或LocalDateTime对象;在将时间值写入数据库时,将Java中的Date或LocalDateTime对象转换为字符串类型的时间偏移量。
要解决这个问题,我们可以使用MyBatis的类型处理器。
类型处理器是MyBatis中用于处理Java类型和数据库类型之间转换的组件,它可以根据需要实现自定义的类型转换逻辑。
下面,我将一步一步地介绍如何使用MyBatis的类型处理器来处理时间偏移量。
第一步,创建自定义的类型处理器类。
我们需要创建一个继承自org.apache.ibatis.type.BaseTypeHandler的自定义类型处理器类。
该类需要实现两个主要的方法:setParameter和getResult。
javapublic class OffsetDateTimeTypeHandler extends BaseTypeHandler<OffsetDateTime> {@Overridepublic void setParameter(PreparedStatement ps, int i, OffsetDateTime parameter, JdbcType jdbcType) throws SQLException {if (parameter != null) {ps.setString(i, parameter.toString());} else {ps.setNull(i, Types.VARCHAR);}}@Overridepublic OffsetDateTime getResult(ResultSet rs, String columnName) throws SQLException {String offsetDateTimeStr = rs.getString(columnName);if (offsetDateTimeStr != null) {return OffsetDateTime.parse(offsetDateTimeStr);} else {return null;}}@Overridepublic OffsetDateTime getResult(ResultSet rs, int columnIndex) throws SQLException {String offsetDateTimeStr = rs.getString(columnIndex);if (offsetDateTimeStr != null) {return OffsetDateTime.parse(offsetDateTimeStr);} else {return null;}}@Overridepublic OffsetDateTime getResult(CallableStatement cs, int columnIndex) throws SQLException {String offsetDateTimeStr = cs.getString(columnIndex);if (offsetDateTimeStr != null) {return OffsetDateTime.parse(offsetDateTimeStr);} else {return null;}}}上面的代码中,我们重写了setParameter和getResult方法来实现转换逻辑。
mybatis basetypehandler注解
在MyBatis 中,BaseTypeHandler是一个接口,用于处理Java 类型和JDBC 类型之间的转换。
当你在MyBatis 中使用Java 类型与数据库交互时,经常需要将Java 类型转换为JDBC 类型以发送到数据库,或将JDBC 类型转换回Java 类型以在应用程序中使用。
BaseTypeHandler接口定义了两个方法:
1.getJavaType(): 返回此处理器关联的Java 类型。
2.getJdbcType(): 返回此处理器关联的JDBC 类型。
为了自定义或扩展类型转换的行为,你可以创建一个实现BaseTypeHandler的类并重写上述方法。
注解(Annotation)在MyBatis 中通常用于配置映射器、参数、结果集等。
例如,
@Select、@Insert、@Update和@Delete等都是MyBatis 的注解,用于简化SQL 语句的编写。
但是,关于你提到的“BaseTypeHandler注解”,我需要澄清一下。
在MyBatis 的官方文档和源代码中,并没有直接提到一个名为“BaseTypeHandler”的注解。
可能你是指如何使用注解来扩展或自定义BaseTypeHandler的行为,或者可能是某个第三方库
或特定的项目中有这样的注解。
如果你想进一步讨论如何使用注解来处理自定义类型或如何自定义BaseTypeHandler,请提供更多的上下文或详细信息,这样我可以为你提供更准确的答案。
mybatis typehandler 原理
Mybatis的TypeHandler主要用于将Java类型和JDBC类型之间进行转换,从而使得Mybatis可以处理各种复杂的数据类型。
TypeHandler的原理如下:
1. 实现TypeHandler接口,重写getNullableResult方法和setNonNullParameter方法,用于将Java类型转换为JDBC类型和将JDBC 类型转换为Java类型。
2. 在Mapper文件中配置TypeHandler,可以在parameterType、resultType、jdbcType等属性上使用TypeHandler,也可以在resultMap 中使用TypeHandler。
3. 当Mybatis执行SQL时,如果查询结果中包含需要转换的Java类型,则Mybatis会通过TypeHandler将JDBC类型转换为Java类型;如果需要插入或更新Java类型,则Mybatis会通过TypeHandler将Java类型转换为JDBC类型。
4. 如果需要自定义TypeHandler,则需要在Mybatis的配置文件中进行配置,并通过Java的SPI机制将自定义TypeHandler注册到Mybatis中。
总的来说,Mybatis的TypeHandler就是通过接口实现和配置文件的配置来实现将Java类型和JDBC类型之间的转换。
Ibatis的类型处理器TypeHandler解析Ibatis允许用户像在hibernate中一样定义自己的类型,但是,用户自定义类型需要与数据库中的字段类型进行对应。
它的处理方法是允许我们扩展TypeHandler。
Ibatis框架在处理该数据类型时就会自动调用TypeHandler进行类型转换,非常方便,ibatis中所有的类型都有它自己的TypeHandler,只是一些常用的数据类类型它已经给我们实现了而已。
在配置文件中,我们有两个地方可以配置这种处理器。
第一个地方是sqlMap文件中标签ResultMap或者ParameterMap中的TypeHandler属性,这里配置的handler是局部属性,只会在该ResultMap中才会进行转换。
<resultMap id="UserOrder" class="UserOrderDO" groupBy="id">......<result property="tripType" column="trip_Type"typeHandler="mon.EnumTypeHandlerCallBack"/> ......</resultMap>第二个地方是sqlMapConfig文件中的标签typeHandlers中配置typeHandle子标签,这里配置的标签是全局属性,任何只要匹配该子标签的地方都会自动使用该Handler.<typeHandlers><typeHandlerjdbcType="CLOB" javaType="ng.String"callback="org.springframework.orm.ibatis.support.ClobStringTypeHandle r"/></typeHandlers>例如这里的全局配置,如果此时某个数据库字段的jdbcType是CLOB类型,并且映射的JavaType 类型是字符串类型,那么就会自动调用这里的callback来实行类型转换。
mybatis string float 类型转换使用MyBatis进行数据库操作时,经常会涉及到字符串和浮点数类型的转换。
在这篇文章中,我们将重点讨论如何在MyBatis中实现这两个类型的转换。
让我们一步一步地来了解吧!第一步:了解MyBatis的类型处理器(TypeHandler)MyBatis的类型处理器(TypeHandler)是用来处理Java类型和数据库类型之间的转换的。
MyBatis提供了如下几个默认的类型处理器:BooleanTypeHandler、ByteTypeHandler、ShortTypeHandler、IntegerTypeHandler、LongTypeHandler、FloatTypeHandler、DoubleTypeHandler、BigDecimalTypeHandler、StringTypeHandler等等。
这些类型处理器可以直接使用,也可以根据需要进行扩展。
第二步:创建自定义的类型处理器如果默认的类型处理器不能满足我们的需求,我们可以通过实现org.apache.ibatis.type.TypeHandler接口来创建自定义的类型处理器。
在这个例子中,我们需要创建一个自定义的类型处理器来处理字符串到浮点数的转换。
首先,创建一个名为FloatToStringTypeHandler的Java类,实现TypeHandler<Float>接口。
代码如下:public class FloatToStringTypeHandler implements TypeHandler<Float> {@Overridepublic void setParameter(PreparedStatement ps, int i, Float parameter, JdbcType jdbcType) throws SQLException {if (parameter != null) {ps.setString(i, String.valueOf(parameter));} else {ps.setString(i, null);}}@Overridepublic Float getResult(ResultSet rs, String columnName) throws SQLException {String result = rs.getString(columnName);if (result != null) {return Float.parseFloat(result);} else {return null;}}@Overridepublic Float getResult(ResultSet rs, int columnIndex) throws SQLException {String result = rs.getString(columnIndex);if (result != null) {return Float.parseFloat(result);} else {return null;}}@Overridepublic Float getResult(CallableStatement cs, int columnIndex) throws SQLException {String result = cs.getString(columnIndex);if (result != null) {return Float.parseFloat(result);} else {return null;}}}在这个自定义的类型处理器中,我们重写了setParameter方法和getResult方法,分别用于将浮点数转换为字符串存入数据库,以及从数据库读取字符串并转换为浮点数。
《MyBatis用户指南》-自定义带参数的类型转换器typeHandler展开全文类型别名只是一个更短的Java类型名。
它只和xml配置有关,并且仅仅是为了缩减冗余的全限定类名的输入量,例如:使用这个配置,"Blog"现在可以在任何"domain.blog.Blog"可以出现的地方使用。
有许多内建的常用Java类型的别名,它们是大小写不敏感的,考虑到重载的名称问题,要注意对于原始类型的特殊处理。
P14:typeHandlers无论何时MyBatis在PreparedStatement设置参数或从ResultSet检索一个值,TypeHandler总是以一种适合于这种Java类型的方式来检索到值。
下面的表格描述了默认的TypeHandler。
P15:你可以覆盖type handler或定制一个去处理不支持或非标准化的类型。
为此,只要实现TypeHandler接口(org.mybatis.type)、映射TypeHandler实现类到一个Java类型(也可以是一个JDBC类型)就行了,例如:使用这样一个TypeHandler会覆盖现存的Java字符串属性、varchar参数和结果的type handler。
注意:MyBatis不会依据数据库元数据自省出类型,所以必须定义参数和结果映射中的类型是一个varchar字段才能钩住正确的type handler. 这是因为MyBatis不会感知到数据类型,除非语句被执行。
objectFactory每当MyBatis创建结果对象的新实例时,它会使用一个ObjectFactory实例来达到此目的。
默认的ObjectFactory只是用默认构造函数来初始化这个目标类,如果参数映射存在,就使用一个参数化的构造函数。
如果想覆盖ObjectFactory的默认行为,可以自己创建一个。
例如:。
mybatis typehandler 枚举类型MyBatis是一款优秀的ORM(Object-RelationalMapping)框架,它提供了许多实用的特性,如TypeHandler。
TypeHandler 是 MyBatis 中用于处理数据库与 Java 类型之间映射的组件。
在 MyBatis 中使用 TypeHandler 可以轻松处理一些复杂的类型转换,其中就包括枚举类型。
枚举类型是 Java 中非常常用的一种数据类型,它可以定义一组常量,并且可以方便地在代码中引用。
在 MyBatis 中,我们可以使用 TypeHandler 将枚举类型与数据库中的字段进行映射。
在编写 TypeHandler 时,我们需要实现 TypeHandler 接口并重写其中的方法。
对于枚举类型,我们需要实现 setNonNullParameter 和 getNullableResult 方法。
setNonNullParameter 方法用于将 Java 对象的属性值转换为数据库中的字段值,getNullableResult 方法则用于将数据库中的字段值转换为 Java 对象的属性值。
两个方法的实现方式如下:public class MyEnumTypeHandler<E extends Enum<E>> implements TypeHandler<E> {private Class<E> enumType;public MyEnumTypeHandler(Class<E> enumType) {this.enumType = enumType;}@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, ());}@Overridepublic E getNullableResult(ResultSet rs, String columnName) throws SQLException {String value = rs.getString(columnName);if (rs.wasNull()) {return null;} else {return Enum.valueOf(enumType, value);}}@Overridepublic E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String value = rs.getString(columnIndex);if (rs.wasNull()) {return null;} else {return Enum.valueOf(enumType, value);}}@Overridepublic E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String value = cs.getString(columnIndex);if (cs.wasNull()) {return null;} else {return Enum.valueOf(enumType, value);}}}上面的代码是一个枚举类型 TypeHandler 的实现,它通过 setNonNullParameter 方法将 Java 对象中的枚举值转换为数据库中的字符串类型,并通过 getNullableResult 方法将数据库中的字符串值转换为Java 对象中的枚举值。
java mybatis booleantypehandler 用法BooleanTypeHandler 是 MyBatis 框架中的一个类型处理器,它用于处理 Java 中的boolean 和 Boolean 类型与数据库中的相应类型之间的转换。
默认情况下,MyBatis 使用BooleanTypeHandler 来处理 Java 中的 boolean 和 Boolean 类型,因此你通常不需要显式地指定它。
但是,如果你需要自定义 boolean 和 Boolean 类型的处理方式,你可以实现自己的类型处理器。
在 MyBatis 中,类型处理器通常用于处理 Java 类型和 JDBC 类型之间的转换。
BooleanTypeHandler 实现了TypeHandler 接口,该接口定义了四个方法,分别是setParameter、getResult、getResult(带 ResultMap 参数)和 setNonNullParameter。
这些方法用于处理 JDBC PreparedStatement 的设置参数和 ResultSet 的获取结果操作。
使用 BooleanTypeHandler 或自定义类型处理器的步骤如下:创建一个类,实现 TypeHandler 接口。
javaimport org.apache.ibatis.type.BaseTypeHandler;import org.apache.ibatis.type.JdbcType;import org.apache.ibatis.type.TypeHandler;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class CustomBooleanTypeHandler extends BaseTypeHandler<Boolean> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Booleanparameter, JdbcType jdbcType) throws SQLException {ps.setBoolean(i, parameter);}@Overridepublic Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {return rs.getBoolean(columnName);}@Overridepublic Boolean getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return rs.getBoolean(columnIndex);}@Overridepublic Boolean getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return cs.getBoolean(columnIndex);}}在 MyBatis 的配置文件(如 mybatis-config.xml)中注册自定义类型处理器。
MyBatis中使用常量或枚举常量替换最近通过代码检查发现,咱们在MyBatis中涉及到一些常量值的用法均是将具体的值直接写在Mapper文件中了,例如:虽然在执行上没有什么问题,但是我还是推荐使用常量来代替这里硬代码,那具体如何做呢?一般情况咱们对一些常量定义方式类似:其实对于数值类型的字段常量,在Mapper文件中直接可以这样写:${@er@USER_STATE_ENABLED}类的全路径及静态常量字段名前均以“@”开头,同时此处使用${}占位符方式即可(由于该字段值是由服务端常量赋值,不会产生注入漏洞)。
但这种写法只允许是数值类型(字符串类型的数字也可以,后面你会知道为什么),如果是字符串常量的就稍微做下处理了,例如现在的常量修改为了:从上图可以看出常量的值并非数字,如果仍然按照上面的方法来进行替换则会抛出语法错误,这是因为上述的替换方法拼出的SQL语句会将常量值直接字面性的拼在SQL语句中,例如:那这种情况如何处理呢?你还记得为了模糊查询而使用的bind元素吗?道理一样:枚举替换自从JDK1.5之后增加了枚举类型,这种类型非常适合表示常量值的,同时限定被调用的值范围,不会误输入错误的值,将隐患消灭在编译期间,其实我还是比较推荐使用枚举的,但如果是枚举上面的方法可行吗?是可行的,但是只能用于bind方式,而且最后“@”的并不是常量名,而是枚举元素名,MyBatis会将枚举元素的字面值当成字段值。
那又有个问题了,如果我想使用枚举,但字段值又是数值时该如何做?其实对于MyBatis专门为枚举提供了两个类型处理器类:●org.apache.ibatis.type.EnumTypeHandler<E>●org.apache.ibatis.type.EnumOrdinalTypeHandler<E>其中EnumOrdinalTypeHandler就是按照枚举元素的位置返回数值的,比如:使用时,只要告诉MyBatis你的类型处理器及你的数据Java类型即可:●javaType:指定你数据对应的Java类型●typeHandler:指定你的类型处理器,这里我们用的是EnumOrdinalTypeHandler,因此你的javaType必须是一个枚举对象。
Ibatis的类型处理器TypeHandler解析Ibatis允许用户像在hibernate中一样定义自己的类型,但是,用户自定义类型需要与数据库中的字段类型进行对应。
它的处理方法是允许我们扩展TypeHandler。
Ibatis框架在处理该数据类型时就会自动调用TypeHandler进行类型转换,非常方便,ibatis中所有的类型都有它自己的TypeHandler,只是一些常用的数据类类型它已经给我们实现了而已。
在配置文件中,我们有两个地方可以配置这种处理器。
第一个地方是sqlMap文件中标签ResultMap或者ParameterMap中的TypeHandler属性,这里配置的handler是局部属性,只会在该ResultMap中才会进行转换。
<resultMap id="UserOrder" class="UserOrderDO" groupBy="id">......<result property="tripType" column="trip_Type"typeHandler="mon.EnumTypeHandlerCallBack"/> ......</resultMap>第二个地方是sqlMapConfig文件中的标签typeHandlers中配置typeHandle子标签,这里配置的标签是全局属性,任何只要匹配该子标签的地方都会自动使用该Handler.<typeHandlers><typeHandlerjdbcType="CLOB" javaType="ng.String"callback="org.springframework.orm.ibatis.support.ClobStringTypeHandle r"/></typeHandlers>例如这里的全局配置,如果此时某个数据库字段的jdbcType是CLOB类型,并且映射的JavaType 类型是字符串类型,那么就会自动调用这里的callback来实行类型转换。
那么Ibatis是如何确定使用哪一个TypeHandler的呢?!它会在自己的局部区域寻找是否在配置文件中配置了Handler,找到了就使用这个handler,如果没有找到,就会查找是否有全局handler,也就是第二种方式配置的handler,这里要注意,可能我们也没有在全局配置文件中配置handler,此时,Ibatis就会根据实际类型配置默认的handler。
我们来看一些关键代码,按照查找步骤,这里我去掉了异常,只看关键的部分。
第一步:从局部Reultmap中取出配置属性。
String propertyName =childAttributes.getProperty("property");String nullValue = childAttributes.getProperty("nullValue"); String jdbcType = childAttributes.getProperty("jdbcType");String javaType = childAttributes.getProperty("javaType");String columnName = childAttributes.getProperty("column");String columnIndex =childAttributes.getProperty("columnIndex");String statementName = childAttributes.getProperty("select"); String resultMapName =childAttributes.getProperty("resultMap");String callback = childAttributes.getProperty("typeHandler"); callback = vars.typeHandlerFactory.resolveAlias(callback);javaType = vars.typeHandlerFactory.resolveAlias(javaType); TypeHandler handler = null;if (callback != null) { // 注意这里,如果配置了就使用这个配置的handler Object impl =Resources.classForName(callback).newInstance();if (implinstanceofTypeHandlerCallback) {handler = new CustomTypeHandler((TypeHandlerCallback) impl);} else if (implinstanceofTypeHandler) {handler = (TypeHandler) impl;} else {throw new NestedRuntimeException ("The class '' is not a valid implementation of TypeHandler or TypeHandlerCallback");}} else {//如果没有配置,就到这里来找handler =resolveTypeHandler(vars.client.getDelegate().getTypeHandlerFactory(), vars.currentResultMap.getResultClass(), propertyName, javaType, jdbcType, true);}第二步,如果局部配置中没有找到,就到下面去找。
publicTypeHandlerresolveTypeHandler(TypeHandlerFactorytypeHandlerFact ory, Class clazz, String propertyName, String javaType, String jdbcType, booleanuseSetterToResolve) {TypeHandler handler = null;if (clazz == null) {// Unknownhandler = typeHandlerFactory.getUnkownTypeHandler();} else if (DomTypeMarker.class.isAssignableFrom(clazz)) {// DOMhandler = typeHandlerFactory.getTypeHandler(String.class, jdbcType); } else if (java.util.Map.class.isAssignableFrom(clazz)) {// Mapif (javaType == null) {handler = typeHandlerFactory.getUnkownTypeHandler(); //BUG 1012591 - typeHandlerFactory.getTypeHandler(ng.Object.class, jdbcType); } else {try {Class javaClass = Resources.classForName(javaType);handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);} catch (Exception e) {throw new NestedRuntimeException("Error. Could not set TypeHandler. Cause: " + e, e);}}} else if (typeHandlerFactory.getTypeHandler(clazz, jdbcType) != null) {// Primitivehandler = typeHandlerFactory.getTypeHandler(clazz, jdbcType);} else {// JavaBeanif (javaType == null) {if (useSetterToResolve) {Class type = PROBE.getPropertyTypeForSetter(clazz, propertyName);handler = typeHandlerFactory.getTypeHandler(type, jdbcType);} else {Class type = PROBE.getPropertyTypeForGetter(clazz, propertyName);handler = typeHandlerFactory.getTypeHandler(type, jdbcType);}} else {try {Class javaClass = Resources.classForName(javaType);handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);} catch (Exception e) {throw new NestedRuntimeException("Error. Could not set TypeHandler. Cause: " + e, e);}}}return handler;}1.相信大家已经很明白了,其实要找一个Handler,主要就是需要javaType和jdbcType,而这两个参数要么通过反射得到,要么通过配置文件中得到。
因此,为了明确我们一般都在配置文件中进行申明。
2.最后来看一点typeHandlerFactory.getTypeHandler(clazz, jdbcType)是怎么实现的。
publicTypeHandlergetTypeHandler(Class type, String jdbcType) {Map jdbcHandlerMap = (Map) typeHandlerMap.get(type);//首先根据JAVA 类型TypeHandler handler = null;if (jdbcHandlerMap != null) {handler = (TypeHandler) jdbcHandlerMap.get(jdbcType);//每个JDBC 类型if (handler == null) {handler = (TypeHandler) jdbcHandlerMap.get(null);}}return handler;}其实一个Handler=javaType+jdbcType。