MybatisPlus字段类型转换的实现示例
作者:氵奄不死的鱼 发布时间:2022-12-09 22:29:13
先来回忆下在mybatis中的resultMap作用和是什么
resultMap的作用是什么
在使用传统的mybatis时,我们一般都会在xml文件定义一个ResultMap
对每个字段都有自己的定义都有两个类型
javaType可以不显式写出来,mybatis可以根据指定的实体类推断出来
jdbcType 也就是对应到数据库中的字段类型
mybatis完成数据库的数据到java实体类型的转换这两个类型是必不可少的。会根据javaType和jdbcType去匹配到对应的处理器完成类型转换
mybatis内置了很多typeHandler在启动时注册
public TypeHandlerRegistry(Configuration configuration) {
this.unknownTypeHandler = new UnknownTypeHandler(configuration);
register(Boolean.class, new BooleanTypeHandler());
register(boolean.class, new BooleanTypeHandler());
register(JdbcType.BOOLEAN, new BooleanTypeHandler());
register(JdbcType.BIT, new BooleanTypeHandler());
register(Byte.class, new ByteTypeHandler());
register(byte.class, new ByteTypeHandler());
register(JdbcType.TINYINT, new ByteTypeHandler());
register(Short.class, new ShortTypeHandler());
register(short.class, new ShortTypeHandler());
register(JdbcType.SMALLINT, new ShortTypeHandler());
register(Integer.class, new IntegerTypeHandler());
register(int.class, new IntegerTypeHandler());
register(JdbcType.INTEGER, new IntegerTypeHandler());
register(Long.class, new LongTypeHandler());
register(long.class, new LongTypeHandler());
register(Float.class, new FloatTypeHandler());
register(float.class, new FloatTypeHandler());
register(JdbcType.FLOAT, new FloatTypeHandler());
register(Double.class, new DoubleTypeHandler());
register(double.class, new DoubleTypeHandler());
register(JdbcType.DOUBLE, new DoubleTypeHandler());
register(Reader.class, new ClobReaderTypeHandler());
register(String.class, new StringTypeHandler());
register(String.class, JdbcType.CHAR, new StringTypeHandler());
register(String.class, JdbcType.CLOB, new ClobTypeHandler());
register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
register(String.class, JdbcType.LONGVARCHAR, new StringTypeHandler());
register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
register(JdbcType.CHAR, new StringTypeHandler());
register(JdbcType.VARCHAR, new StringTypeHandler());
register(JdbcType.CLOB, new ClobTypeHandler());
register(JdbcType.LONGVARCHAR, new StringTypeHandler());
register(JdbcType.NVARCHAR, new NStringTypeHandler());
register(JdbcType.NCHAR, new NStringTypeHandler());
register(JdbcType.NCLOB, new NClobTypeHandler());
register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
register(JdbcType.ARRAY, new ArrayTypeHandler());
register(BigInteger.class, new BigIntegerTypeHandler());
register(JdbcType.BIGINT, new LongTypeHandler());
register(BigDecimal.class, new BigDecimalTypeHandler());
register(JdbcType.REAL, new BigDecimalTypeHandler());
register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
register(JdbcType.NUMERIC, new BigDecimalTypeHandler());
register(InputStream.class, new BlobInputStreamTypeHandler());
register(Byte[].class, new ByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
register(byte[].class, new ByteArrayTypeHandler());
register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.BLOB, new BlobTypeHandler());
register(Object.class, unknownTypeHandler);
register(Object.class, JdbcType.OTHER, unknownTypeHandler);
register(JdbcType.OTHER, unknownTypeHandler);
register(Date.class, new DateTypeHandler());
register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
register(JdbcType.TIMESTAMP, new DateTypeHandler());
register(JdbcType.DATE, new DateOnlyTypeHandler());
register(JdbcType.TIME, new TimeOnlyTypeHandler());
register(java.sql.Date.class, new SqlDateTypeHandler());
register(java.sql.Time.class, new SqlTimeTypeHandler());
register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());
register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler());
register(Instant.class, new InstantTypeHandler());
register(LocalDateTime.class, new LocalDateTimeTypeHandler());
register(LocalDate.class, new LocalDateTypeHandler());
register(LocalTime.class, new LocalTimeTypeHandler());
register(OffsetDateTime.class, new OffsetDateTimeTypeHandler());
register(OffsetTime.class, new OffsetTimeTypeHandler());
register(ZonedDateTime.class, new ZonedDateTimeTypeHandler());
register(Month.class, new MonthTypeHandler());
register(Year.class, new YearTypeHandler());
register(YearMonth.class, new YearMonthTypeHandler());
register(JapaneseDate.class, new JapaneseDateTypeHandler());
// issue #273
register(Character.class, new CharacterTypeHandler());
register(char.class, new CharacterTypeHandler());
}
当然我们不指定类型的话mybatis也具备自动推断类型的能力。
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#createAutomaticMappings
创建自动的字段映射根据数据库查询结果类型,和我们指定的对象字段类型做映射
mybatisPlus如何完成字段映射
当然也可以指定resultMap
@TableNam中有resultMap属性
/**
* 实体映射结果集,
* 只生效与 mp 自动注入的 method
*/
String resultMap() default "";
@Mapper
public interface UserDoMapper extends BaseMapper<User> {
@Results(
id = "userResultMap",
value = {@Result(column = "id",property = "id",javaType = Integer.class,jdbcType = JdbcType.INTEGER),
@Result(column = "user_name",property = "userName",javaType = String.class,jdbcType = JdbcType.VARCHAR),
@Result(column = "pass_word",property = "passWord",javaType = String.class,jdbcType = JdbcType.VARCHAR),
@Result(column = "real_name",property = "realName",javaType = String.class,jdbcType = JdbcType.VARCHAR),
@Result(column = "json_arr",property = "jsonArr",typeHandler = StringToJsonArrayBaseTypeHandler.class),
}
)
@Select("SELECT * FROM user ${ew.customSqlSegment}")
User searchDetail( @Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
@TableName(resultMap = "userResultMap")
public class User {
@TableField(jdbcType = JdbcType.INTEGER)
private Integer id;
@TableField(jdbcType = JdbcType.VARCHAR)
private String userName;
@TableField(jdbcType = JdbcType.VARCHAR)
private String passWord;
@TableField(jdbcType = JdbcType.VARCHAR)
private String realName;
@TableField(typeHandler = StringToJsonArrayBaseTypeHandler.class)
private List<String> jsonArr;
}
那么我们不想手动定义ResutMap但是又想处理一些复杂类型的转换 就可以使用autoResultMap
自动映射
我们在使用mybatisPlus时在大多数情况是不会定义resultMap的,那么mybatisPlus是如何完成字段映射的,那么答案显而易见,就是使用myabtis的字段自动创建映射的功能。
自动映射的方案有什么缺点?
1.对于复杂的类型,无法指定转换方案,无法使用自定义的类型转换器。
2.无法使用关联查询
开启autoResultMap
@TableName(autoResultMap = true)
那么mybatisPlus会根据我们的实体类的类型,为我们自动注入resultMap,注入的resultMap也会自动推断出需要使用的类型转换器当然我们也可以指定
例如
@TableField(typeHandler = StringToJsonArrayBaseTypeHandler.class)
private List<String> jsonArr;
也因此说,对于查询来说,mybatisPlus通过@TableField指定类型转换器,一定要开启autoResultMap才能生效了。另外mybatisPlus只会为BaseMapper中的方法生成resultMap,而我们自定义的方法,是不会生成的。
例如
@Mapper
public interface UserDoMapper extends BaseMapper<User> {
@Select("SELECT * FROM user ${ew.customSqlSegment}")
User searchDetail( @Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
这种写法autoResultMap和指定的类型转换器是不会生效的。如果有复杂字段转换需求,需要通过@Results标签定义resultMap
例如
以及通过@ResultMap标签进行引用
@TableField是能够指定jdbcType的
不指定jdbcType时mybatis往往也能够完成自动转换,例如java中的String自然对应到数据库的VAERCHAR
在mybatis无法根据自动完成javaType到jdbcType的转换时,可以使用@TableField注解完成转换,例如我们想将一个数据库中的VARCHAR类型映射成为java中的Integer,对于插入操作时又要完成Integer到VARCHAR的转换,如果不指定jdbcType那么插入操作将会报错
@TableField(jdbcType = JdbcType.VARCHAR)
private Integer age;
mybatis如何完成查询参数转换
前面看的是对于查询结果的转换,那么对于插入,更新,查询等操作,也有一个javaType到jdbcType的转换,对于复杂的字段类型 例如集合转json又是如何生效的?
还是先看传统mybatis定义映射的写法
<insert id="insert" parameterType="com.imtech.yasha.sp.common.mapper.dto.sp.ZbLabourBidAuctionList" >
insert into zb_labour_bid_auction_list (id, uuid, uuid_t,
creater, create_time, updater,
update_time, item_d, item_n,
order_no, list_no, sub_project_name,
construction_tech, unit, project_quantity,
unit_price, total, remark,
supplier_no, supplier_name)
values (#{id,jdbcType=BIGINT}, #{uuid,jdbcType=VARCHAR}, #{uuidT,jdbcType=VARCHAR},
#{creater,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{updater,jdbcType=VARCHAR},
#{updateTime,jdbcType=TIMESTAMP}, #{itemD,jdbcType=VARCHAR}, #{itemN,jdbcType=VARCHAR},
#{orderNo,jdbcType=VARCHAR}, #{listNo,jdbcType=VARCHAR}, #{subProjectName,jdbcType=VARCHAR},
#{constructionTech,jdbcType=VARCHAR}, #{unit,jdbcType=VARCHAR}, #{projectQuantity,jdbcType=NUMERIC},
#{unitPrice,jdbcType=NUMERIC}, #{total,jdbcType=NUMERIC}, #{remark,jdbcType=VARCHAR},
#{supplierNo,jdbcType=VARCHAR}, #{supplierName,jdbcType=VARCHAR})
</insert>
在参数上一般都会定义jdbcType,至于JavaType可以从parameterType指定的class中推断出来,这样javaTyp和jdbcType都被确定下来,很容易匹配到对应的处理器进行类型转换。
那么在mybatisPlus中显然不会为每个入参字段定义jdbcType,那么对于入参是如何进行转换的,复杂类型又是如何指定的
@TableField(typeHandler = StringToJsonArrayBaseTypeHandler.class)
private List<String> jsonArr;
答案也是通过@TableField指定的,而且即使关闭autoResultMap,对于查询参数的转换,指定的类型转换器和jdbcType也是会生效的。
来源:https://blog.csdn.net/qq_37436172/article/details/129466009


猜你喜欢
- DllImport是System.Runtime.InteropServices命名空间下的一个属性类,其功能是提供从非托管DLL导出的函数
- 一些Java项目中在mybatis与spring整合中有MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接
- 本文实例讲述了Android布局之LinearLayout自定义高亮背景的方法。分享给大家供大家参考,具体如下:首先创建linearlayo
- 本文实例讲述了spring AOP的Around增强实现方法。分享给大家供大家参考,具体如下:一 配置<?xml version=&q
- 本文实例为大家分享了Android Scroller实现弹性滑动的具体代码,供大家参考,具体内容如下首先看下实现效果,可以看到当我们手指松开
- 开发环境 android studio 3.0.1 已支持 kotlin1、定义接口interface CallBack{ fun call
- 最近研究了下Java socket通信基础,利用代码实现了一个简单的多人聊天室功能,现把代码共享下,希望能帮到有兴趣了解的人。目录结构:Ch
- 前言在之前 LiveData 源码浅析的博客中提到了 ViewModel 组件,当时对 ViewModel 的解释是 “
- 今天Android Studio提示我这个东东。。。为了加快Gradle的构建速度,我点击了“Update”。。。之后工程一片红,全是R文件
- 前言为什么要动态设置字体大小?由于项目面对的是中老年客户项目中自带的字体无法满足客户需求。Android应用字体大小默认随系统设置的字体大小
- 本文实例为大家分享了Android实现秒表功能的具体代码,供大家参考,具体内容如下设计完成一个秒表,具备启停功能,正确使用工作线程完成界面刷
- java Long类型转为String类型1、Long.ValueOf("String")返回Long包装类型数据包装类
- 前段时间由于VSS上的一个项目要给2个公司开发使用,而2个公司的需求不同 就把该项目复制到VSS上的另外一个目录,结果在别人的电脑取出并打开
- 前言在日常开发中,除了修改请求参数、设置响应header,响应body外,还有一种需求就是url重新,或者是修改url,这里简述一下怎么在z
- 昨天晚上写代码的时候偶然发现 DateTime 里出现了星期几,当时一阵凌乱,去网上百度没有详细解决办法,很多人说可以用用 ToString
- java 值Document解析xml详细介绍使用jar包:jdom.jar配置文件格式 global.xml一、获取输入的值组成的结点我们
- 废话不多说了,直接步入正题了。1、批量添加元素session.insert(String string,Object o)public vo
- 在封装中有一种特殊的类,能够把基本的数据类型进行转换来方便实际的使用。我们在之前提到的一些数据类型,最明显的特征是所有字母为小写状态,那么经
- 一、需求背景有时候,我们需要在屏幕上显示新的信息,同时移除旧的信息,一般情况下我们通过VISIBILITY或者GONE来对需要显示或者隐藏的
- 目前做的项目使用的是MAVEN来管理jar包,这也是我第一次接触maven,感觉非常好,再也不用一个一个去添加和下载jar包了,直接在mav