在做项目的时候,数据库中的所有字段被设置为全都不能为null,但是在我们开发过程中,插入一些记录的时候,实体类中的一些字段如果页面没有传入,则默认就会被设置为null,这样的话,在执行插入语句的时候,数据库就会报错,说指定的列不能为null,这样数据就无法插入。

在网上找了一下,都没有这种处理的方式,但是找到了mybatis的类型转换,说的是在java中的类型和数据库中的类型不一致的时候,需要自己处理数据库类型和java中类型之间的转换,这个就是通过mybatis的typehandler来处理的。

查看typehandler这个接口发现有一下几个需要实现的方法:


public String getResult(ResultSet rs, String columnName) throws SQLException;

public String getResult(ResultSet rs, int columnIndex) throws SQLException;

public String getResult(CallableStatement cs, int columnIndex) throws SQLException;

public void setParameter(PreparedStatement pstmt, int index, String value, JdbcType jdbcType) throws SQLException;


在这4个需要实现的方法中,我们只需要关注第4个方法,因为这个方法是mybatis在给参数设置值的时候,会调用到此方法,基于这样的原因,如果我们在 setParameter中判断当前参数传入的值,如果value=null,我们就将参数的值设置为空的字符串,这样就避免了在执行插入语句的时候,传入null的情况,数据库中也不会报错,问题就解决了。


代码:

package zzt.ssm.controller.typehandler;


import java.sql.CallableStatement;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;


import org.apache.ibatis.type.BaseTypeHandler;

import org.apache.ibatis.type.JdbcType;

import org.apache.ibatis.type.TypeHandler;


public class NullValueHandler implements TypeHandler<String> {


    @Override

    public String getResult(ResultSet rs, String columnName) throws SQLException {

        return rs.getString(columnName);

    }


    @Override

    public String getResult(ResultSet rs, int columnIndex) throws SQLException {

        return rs.getString(columnIndex);

    }


    @Override

    public String getResult(CallableStatement cs, int columnIndex) throws SQLException {

        return cs.getString(columnIndex);

    }


    @Override

    public void setParameter(PreparedStatement pstmt, int index, String value, JdbcType jdbcType) throws SQLException {

        if(value == null && jdbcType == JdbcType.VARCHAR){//判断传入的参数值是否为null

            pstmt.setString(index,"");//设置当前参数的值为空字符串

        }else{

            pstmt.setString(index,value);//如果不为null,则直接设置参数的值为value

        }

    }


}



以上是已经定义好的一个typehandler类,但是还需要我们在配置文件中注册我们自定义的typehandler,因为使用了和spring继承的配置,所以注册typehandler的配置在spring的配置文件中的配置如下:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        <property name="dataSource" ref="dataSource" />

        <!-- 指定mapper文件位置 -->

        <property name="mapperLocations" value="classpath*:**/dao/*Mapper.xml" />

        <!-- 指定别名 -->

        <property name="typeAliasesPackage" value="zzt.ssm.domain" />

         <property name="typeHandlersPackage" value="zzt.ssm.c ontroller.typehandler"/>

    </bean>

这里指定了 typeHandlersPackage属性,value为自定义的typehandler的包名,这样mybatis会将这个包下面的所有的类注册为对应的TypeHandler类。


到这里我们的自定义的TypeHandler就配置好了,

下面在我们的mybatis的mapper中,指定对应的typehandler为自定义的TypeHandler类就可以了


<!-- 添加人员信息 -->

    <insert id="insertPerson" parameterType="Person">

        insert into person(name,sex,address)

            values( #{name,jdbcType=VARCHAR,typeHandler=zzt.ssm.controller.typehandler.NullValueHandler},#{sex},#{address} )

    </insert>


这里在name参数上指定了 typeHandler配置,这样在数据插入的时候,mybatis会调用自定义的TypeHandler类来处理name参数的值,即,如果name的值为null则设置为空字符串,如果不为空,则直接设置值。



现在如果我们测试,在前端如果没有传入name属性的情况下,数据库中插入的数据是否为空字符串,而不是null


直接在浏览器的地址栏中输入, http://localhost:8080/springmvcmybatis/person/savePerson.action?address=dddd

这里我们什么参数都没有传入,那么在springmvc中Controller中,就会将对应的实体的属性值设置为null

mybatis插入数据时处理为null的属性_java

 

 


现在我们看到,页面传入的属性值已经被注入到对应的实体的属性中,没有传入的属性全都是null。


此时查看数据库中插入的记录,可以看到name的值为空字符串,而没有处理的sex的值为null

mybatis插入数据时处理为null的属性_自定义_02

 

 

 

 

 





实现自定义的除了使用以上这种实现 TypeHandler接口的方式外,还可以直接继承BaseTypeHandler来实现。

mybatis官方文档: http://mybatis.org/mybatis-3/zh/configuration.html#typeHandlers