Mybatis是一个优秀的持久层框架,它提供了丰富的功能来简化数据库操作。在Mybatis中,TypeHandler是用于处理Java对象与数据库字段之间的类型转换的组件。自定义TypeHandler可以帮助我们处理一些特殊的数据类型或者自定义的数据类型。
自定义TypeHandler需要实现org.apache.ibatis.type.TypeHandler接口,并重写其中的方法。主要包括以下几个方法:
- setParameter:用于将Java对象转换为JDBC参数进行设置。
- getResult:用于将数据库字段的值转换为Java对象进行返回。
- getResult(CallableStatement cs, int columnIndex):用于将数据库字段的值转换为Java对象进行返回,支持存储过程。
- getResult(ResultSet rs, String columnName):用于将数据库字段的值转换为Java对象进行返回,通过字段名获取值。
- getResult(ResultSet rs, int columnIndex):用于将数据库字段的值转换为Java对象进行返回,通过字段索引获取值。
下面是一个自定义TypeHandler的示例代码:
java
public class MyCustomTypeHandler implements TypeHandler<MyCustomType> {
@Override
public void setParameter(PreparedStatement ps, int i, MyCustomType parameter, JdbcType jdbcType) throws SQLException {
// 将Java对象转换为JDBC参数进行设置
ps.setString(i, parameter.toString());
}
@Override
public MyCustomType getResult(ResultSet rs, String columnName) throws SQLException {
// 将数据库字段的值转换为Java对象进行返回
String value = rs.getString(columnName);
return new MyCustomType(value);
}
@Override
public MyCustomType getResult(ResultSet rs, int columnIndex) throws SQLException {
// 将数据库字段的值转换为Java对象进行返回
String value = rs.getString(columnIndex);
return new MyCustomType(value);
}
@Override
public MyCustomType getResult(CallableStatement cs, int columnIndex) throws SQLException {
// 将数据库字段的值转换为Java对象进行返回,支持存储过程
String value = cs.getString(columnIndex);
return new MyCustomType(value);
}
}
在Mybatis的配置文件中,我们需要注册自定义的TypeHandler。可以通过在标签中添加子标签来进行配置,示例如下:
xml
<typeHandlers>
<typeHandler handler="com.example.MyCustomTypeHandler"/>
</typeHandlers>
这样,Mybatis就会在需要处理MyCustomType类型的字段时,使用我们自定义的TypeHandler进行类型转换。
如果项目是使用SpringBoot开发,也可以直接在类配置器的获取sqlSessionFactory实例的方法中进行注入。
其实Mybatis默认提供了一些基本类型的类型转换器,我们可以参照这些类型转换器去自定义。
在这个包目录下:org.apache.ibatis.type
我们随便看一个实现类:BigDecimalTypeHandler
java
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.apache.ibatis.type;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BigDecimalTypeHandler extends BaseTypeHandler<BigDecimal> {
public BigDecimalTypeHandler() {
}
public void setNonNullParameter(PreparedStatement ps, int i, BigDecimal parameter, JdbcType jdbcType) throws SQLException {
ps.setBigDecimal(i, parameter);
}
public BigDecimal getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getBigDecimal(columnName);
}
public BigDecimal getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getBigDecimal(columnIndex);
}
public BigDecimal getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getBigDecimal(columnIndex);
}
}
很简单,就是继承了BaseTypeHandler
接口,然后实现其中的抽象方法就可以了。
我们可以自己实现这个BigDecimal的类型转换器,比如我这里自定义了一个BigDecimal类型转换器,默认将查询的结果小数点后面的0去掉。
java
package com.au.sa.storeRebate.common.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author xiaohuihui
* @creteTime 2024-05-01 10:53
* @description
*/
@Component
public class BigDecimalTypeHandler extends BaseTypeHandler<BigDecimal> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, BigDecimal parameter, JdbcType jdbcType) throws SQLException {
ps.setBigDecimal(i, parameter);
}
@Override
public BigDecimal getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getBigDecimal(columnName).stripTrailingZeros();
}
@Override
public BigDecimal getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getBigDecimal(columnIndex).stripTrailingZeros();
}
@Override
public BigDecimal getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getBigDecimal(columnIndex).stripTrailingZeros();
}
}
然后在Mybatis数据源的配置类中,注入Handler的包扫描路径就可以了。
java
@Primary
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("master") DataSource dataSource, @Qualifier("mybatisPlusInterceptor") MybatisPlusInterceptor mybatisPlusInterceptor) throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
sqlSessionFactory.setDataSource(dataSource);
LOGGER.info("数据库连接池信息:{}", ((HikariDataSource)dataSource).getIdleTimeout());
GlobalConfig globalConfig=new GlobalConfig();
globalConfig.setMetaObjectHandler(metaObjectHandler);
sqlSessionFactory.setGlobalConfig(globalConfig);
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setMapUnderscoreToCamelCase(true);
if (Objects.equals(isShowSql, true)) {
configuration.setLogImpl(StdOutImpl.class);
}
configuration.setCacheEnabled(false);
configuration.addInterceptor(mybatisPlusInterceptor);
sqlSessionFactory.setConfiguration(configuration);
sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
sqlSessionFactory.setTypeHandlersPackage("com.au.sa.storeRebate.common.handler");
return sqlSessionFactory.getObject();
}
就是这一行代码:
java
sqlSessionFactory.setTypeHandlersPackage("com.au.sa.storeRebate.common.handler");
也可以采用这种形式:
java
@Resource
private BigDecimalTypeHandler bigDecimalTypeHandler;
sqlSessionFactory.setTypeHandlers(bigDecimalTypeHandler);
实现的效果:
返回的结果自动将小数点后面的0去除了。