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<String, Object> 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)]