今日项目中遇到了一个需求,就是把所有的float的值,插入数据库的时候默认都设置为0,我们都知道页面上的值如果不传过来的话,在action用@RequestBody接受这个对象的时候,里面的值就是null的,ibatis有一个很奇怪的null值处理方式,就是我不传值的话,他会把null也给插入进去,这个时候数据库再去设置的默认值就不起作用了;
这个时候有几个解决办法,其中最简单的方法就是在插入的时候先去判断一下如果这个是null的话,就去给它设置为0,
但是这种方法很麻烦,每个地方都需要去写;
然后奇思妙想,找个了另外一种办法,就是在使用spring的拦截器,在接受到请求的时候拦截一下,获取request里面传过来的值,然后利用反射把float型的null值转换成0,
结果发现了另外一个问题,那就是用前端用ajax传过来的是一个对象,而且后台用@RequestBody接收的话,request里面是没有值的;不过是可以解析出来里面的值的,只不过这种办法太复杂,所以给舍弃了;
最后我找到了TypeHandlerCallback Ibatis的类型处理器
这个类型处理器非常简单实用,不过网上的解释的太复杂了,我简单解释一下,就是说这个解析器主要处理两个对象,一个是数据库类型,一个是Java类型,然后他提供了三个方法,一个是查询方法,我们可以把数据库的查询字段转换成java的查询字段,一个是set方法,在我们修改和插入的时候使用,这个会把我们插入的java字段转换成数据库类型的字段。还有一个定位方法,主要能够定位到为null的字段插入下标;
我们先看get方法
@Override
public Object getResult(ResultGetter arg0) throws SQLException {
Object result = null;
if (null !=arg0.getObject()) {
result =arg0.getFloat();
}else{
result=0F;
}
return result;
}
get方法会接收数据库字段的类型,当然这个类型是通过配置文件配置的,这个后面再说;他会去判断我接收的数据库查询字段类型和值,这里如果不为空的话,那么就直接返回这个值,去跟我们的对象匹配,如果为空的话,那么这个值就设置成0;
再来看看set方法
@Override
public void setParameter(ParameterSetter arg0, Object arg1)
throws SQLException {
if (null == arg1) {
arg0.setObject(0F); // 若没有传值则设置成0
} else {
arg0.setObject(arg1);
}
}
set方法接收两个参数,第一个是数据库类型的参数,第二个是Java类型的参数
有了这两个参数,你可以在里面随意转换,根据你的业务,想怎么玩就怎么玩;
最后说一下配置文件
现在主要有两种配置,一种是在sqlMap中配置,只有配置过的才生效
<resultMap class="com.xxx.pojos.People" id="people">
<result property="id" column="id" javaType="int" jdbcType="INT"/>
<result property="gender" column="gender" javaType="string" nullValue="male" jdbcType="VARCHAR" typeHandler="com.xxx.typeHandler.GenderTypeHandlerCallback" />
</resultMap>
还有一种是全局的配置,在所有地方只要符合类型的都生效
<typeHandler jdbcType="REAL" javaType="java.lang.Float" callback="monitor.handle.GenderEnumTypeHandler"/>
这里只要数据库类型是REAL,并且Java类型是Float的,都会生效;