栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

重学Mybatis:类型处理器,这个你得会玩

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

重学Mybatis:类型处理器,这个你得会玩

return result == 0 && rs.wasNull() ? null : result;
}

@Override
public Integer getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
int result = rs.getInt(columnIndex);
return result == 0 && rs.wasNull() ? null : result;
}

@Override
public Integer getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
int result = cs.getInt(columnIndex);
return result == 0 && cs.wasNull() ? null : result;
}
}

mybatis内部默认实现了很多类型转换器,每种类型转换器能够处理哪些java类型以及能够处理的JdbcType的类型,这些都在TypeHandlerRegistry进行注册的,大家可以去看一下这个类源码,IntegerTypeHandler也是在这个类中进行注册的,代码如下:

register(Integer.class, new IntegerTypeHandler());
register(int.class, new IntegerTypeHandler());
register(JdbcType.INTEGER, new IntegerTypeHandler());

所以当我们参数是Integer或者int类型的时候,mybatis会调用IntegerTypeHandler转换器中的setInt方法去设置参数,上面我们的UserModel的id字段是Integer类型的,所以插入数据的时候会调用IntegerTypeHandler处理器中的setInt方法去设置参数,当mybatis将t_user表的数据自动映射为UserModel类型的时候,mybatis会发现id类型是Integer类型,然后会找到IntegerTypeHandler中对应的读取结果集的方法去读取数据,即调用ResultSet的getInt方法读取id字段的数据,然后赋值给UserModel中的id属性。

自定义类型转换器

我们在用户表新增一个性别字段sex,java中我们通过一个枚举来表示这个类型,db脚本如下:

DROp DATABASE IF EXISTS javacode2018;
CREATE DATABASE javacode2018;

USE javacode2018;

DROP TABLE IF EXISTS t_user;
CREATE TABLE t_user(
id int AUTO_INCREMENT PRIMARY KEY COMMENT ‘用户id’,
name VARCHAr(32) NOT NULL DEFAULT ‘’ COMMENT ‘用户名’,
age SMALLINT NOT NULL DEFAULT 1 COMMENT ‘年龄’,
sex SMALLINT DEFAULT 0 COMMENT ‘性别,0:未知,1:男,2:女’
) COMMENT ‘用户表’;
INSERT INTO t_user VALUES (1,‘路人甲Java’,30,1),(2,‘林志玲’,45,2);

t_user对应的Model如下:

@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class UserModel implements Serializable {
private Integer id;
private String name;
private Integer age;
private SexEnum sex;
}

sex是一个枚举类型,枚举定义如下:


public enum SexEnum {
UNKNOW(0, “未知”),
MAN(1, “男”),
WOMAN(2, “女”);

private Integer value;
private String name;

SexEnum(Integer value, String name) {
this.value = value;
this.name = name;
}

public Integer getValue() {
return value;
}

public String getName() {
return name;
}

public static SexEnum getByValue(Integer value) {
for (SexEnum item : values()) {
if (item.getValue().equals(value)) {
return item;
}
}
return null;
}
}

我们来写一个查询如下:

SELECT id,name,age,sex FROM t_user

这个大家都很熟悉了,查询t_user表,每行结果转换为一个UserModel对象,最后返回一个List集合,这个查询运行会不会有什么问题?

确实会报错,如下:

Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column ‘sex’ from result set. Cause: java.lang.IllegalArgumentException: No enum constant com.javacode2018.chat05.demo10.enums.SexEnum.1

at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:149)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:147)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:93)

sex字段在t_user中是数字类型的,最后通过mybatis查询,需要赋值给UserModel中的sex字段,这个字段是一个枚举类型的,mybatis不知道这两者之间如何进行转换,所以报错了。

此时需要我们指定一个转换规则,来告知mybatis如何进行转换,需要我们用到自定义类型转换器了。

自定义一个类型转换器SexEnumTypeHandle,用来处理sex字段和SexEnum枚举之间的相互转换,代码如下:

package com.javacode2018.chat05.demo10.typehandle;

import com.javacode2018.chat05.demo10.enums.SexEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@Slf4j
public class SexEnumTypeHandle extends BaseTypeHandler {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, SexEnum parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getValue());
log.info(“{}”, parameter);
}

@Override
public SexEnum getNullable Java开源项目【ali1024.coding.net/public/P7/Java/git】 Result(ResultSet rs, String columnName) throws SQLException {
log.info(“{}”, columnName);
Object object = rs.getObject(columnName);
Integer sex = object != null && object instanceof Integer ? (Integer) object : null;
return SexEnum.getByValue(sex);
}

@Override
public SexEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
log.info(“{}”, columnIndex);
Object object = rs.getObject(columnIndex);
Integer sex = object != null && object instanceof Integer ? (Integer) object : null;
return SexEnum.getByValue(sex);
}

@Override
public SexEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
log.info(“{}”, columnIndex);
Object object = cs.getObject(columnIndex);
Integer sex = object != null && object 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源 instanceof Integer ? (Integer) object : null;
return SexEnum.getByValue(sex);
}
}

自定义类型转换器可以直接继承BaseTypeHandler,后面有个泛型,泛型类型为需要处理的java类型,即SexEnum。

类型转换器定义好了,需要将其注册到mybatis中,需要在mybatis配置文件中加入:

再次运行一下上面的查询,对应测试用例:

com.javacode2018.chat05.demo10.Demo10Test#getModelList

@Test
public void getModelList() throws IOException {
try (SqlSession sqlSession = this.sqlSessionFactory.openSession(true) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map paramMap = new HashMap<>();
List userModelList = mapper.getList1(paramMap);
log.info(“{}”, userModelList);
}
}

运行结果:

26:26.144 [main] DEBUG c.j.c.d.mapper.UserMapper.getList1 - ==> Preparing: SELECT id,name,age,sex FROM t_user
26:26.167 [main] DEBUG c.j.c.d.mapper.UserMapper.getList1 - ==> Parameters:
26:26.187 [main] INFO c.j.c.d.typehandle.SexEnumTypeHandle - sex

最后

总而言之,面试官问来问去,问的那些Redis知识点也就这么多吧,复习的不够到位,知识点掌握不够熟练,所以面试才会卡壳。将这些Redis面试知识解析以及我整理的一些学习笔记分享出来给大家参考学习

还有更多学习笔记面试资料也分享如下:

EnumTypeHandle - sex

最后

总而言之,面试官问来问去,问的那些Redis知识点也就这么多吧,复习的不够到位,知识点掌握不够熟练,所以面试才会卡壳。将这些Redis面试知识解析以及我整理的一些学习笔记分享出来给大家参考学习

还有更多学习笔记面试资料也分享如下:

[外链图片转存中…(img-RkEuqjiH-1650452739375)]

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/820413.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号