欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Mybatis+Oracle搭配insert空值报错之myBatis+mysql驱动+oracle驱动的源码分析

程序员文章站 2022-06-21 23:44:51
为了便于测试,先给出Demo代码: mybatis-oracle-config.xml 1 2

为了便于测试,先给出demo代码:

mybatis-oracle-config.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <!doctype configuration public "-//mybatis.org//dtd config 3.0//en"
 3         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 4 
 5 <configuration>
 6     <properties>
 7         <property name="driver" value="oracle.jdbc.driver.oracledriver"/>
 8         <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521/orcl"/>
 9     </properties>   
10     <environments default="dev">
11         <environment id="dev">        
12             <transactionmanager type="jdbc" />
13                <datasource type="pooled">
14                 <property name="driver" value="${driver}"></property>
15                 <property name="url" value="${url}"></property>
16                 <property name="username" value="gys"></property>
17                 <property name="password" value="gys"></property>
18             </datasource>
19         </environment>
20 
21     </environments>
22     <mappers>       
23         <mapper resource="mapper/oracle/user.xml"></mapper>
24     </mappers>
25 </configuration>

user.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <!doctype mapper public "-//mybatis.org//dtd mapper 3.0//en"
 3         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 4 <mapper namespace="dao.oracle.iusermapper">
 5     <insert id="insertuser" parametertype="model.oracle.user">
 6         insert into users
 7         (name,age)
 8         values
 9         (#{name},#{age})
10     </insert>
11 
12 </mapper>

main()入口方法

public static void main(string[] args) throws exception{  
        sqlsessionfactorybuilder builder=new sqlsessionfactorybuilder();
        sqlsessionfactory sqlsessionfactory=builder.build(resources.getresourceasstream("mybatis-oracle-config.xml"),"dev");
        sqlsession sqlsession=sqlsessionfactory.opensession(true);
        iusermapper usermapper=sqlsession.getmapper(iusermapper.class);
        user user=new user();
        //user.setname("a");//故意注释,不设置。模拟空值
        user.setage(20);
        int count=usermapper.insertuser(user);
        system.out.println(count == 1 ? "插入成功" : "插入失败");
        list<user> list=usermapper.getuserlist();
        for (user user1 : list) {
            system.out.println(user1.tostring());
        }
        sqlsession.close();
    }

源码分析请参考这篇博客:mybatis+oracle搭配insert空值报错之mybatis+mysql驱动+oracle驱动的源码分析

总结一下空值报错的原因:

mybatis在build阶段,不知道这个参数的具体jdbctype类型,mybatis会给他一个默认的1111编号;

在mybatis运行阶段,空值 +111编号条件就使得mybatis去调用了oracle驱动中预编译器的setnull()方法;

因为oracle不识别1111编号,所以直接就抛出了异常。

方法1:构建时办法

在user.xml的sql中,给参数指明具体的jdbctype类型,让oracle预编译器能够知道以varchar或者numeric方式处理这种空值。

修改后的代码如下红色地方。 

<?xml version="1.0" encoding="utf-8"?>
<!doctype mapper public "-//mybatis.org//dtd mapper 3.0//en"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.oracle.iusermapper">
    <insert id="insertuser" parametertype="model.oracle.user">
        insert into users
        (name,age)
        values
        (#{name,jdbctype=varchar},#{age})
    </insert>
</mapper>

 方法2:运行时办法 

编写自定义的typehandler。

当mybatis不知道具体的jdbctype类型时,在自定义typehandler中指定jdbctype。

数据库中常用的就两种字段,一个varchar字段,一个numberic字段。所以定义两个typehandler。

public class mynumbernulltypehandler extends integertypehandler {
    @override
    public void setparameter(preparedstatement ps, int i, integer parameter, jdbctype jdbctype) throws sqlexception {
        super.setparameter(ps, i, parameter, jdbctype.numeric);
    }
}
public class mystringnulltypehandler extends stringtypehandler {
    @override
    public void setparameter(preparedstatement ps, int i, string parameter, jdbctype jdbctype) throws sqlexception {       
        super.setparameter(ps,i,parameter,jdbctype.varchar);
    }
}

mybatis-oracle-config.xml中的properties后面添加如下配置

  <typehandlers>
       <typehandler handler="handler.oracle.mystringnulltypehandler" />
        <typehandler handler="handler.oracle.myintegernulltypehandler" />
    </typehandlers>

综合比较后感觉方法2是一个一劳永逸的方法。