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是一个一劳永逸的方法。