解决mybatis使用char类型字段查询oracle数据库时结果返回null问题
同事在学mybatis时,遇到了一个问题就是,使用char类型字段作为查询条件时一直都查不出数据,其他类型的则可以。
使用的数据库是oracle,查询条件字段类型是char(50),java代码对应的是String类型。
后来经过排查,是由于在oracle中,char类型字段,如果内容长度不够,会自动以空格方式补足长度。如字段namechar(5),若值为sgl,那么oracle会自动用空格补足长度,最终值为sgl。
一、解决方法:
方法1:先用trim()函数把值去掉两边空格再作为条件查询,如:
select*fromdatawheredata.name=#{name}
改为:
select*fromdatawheretrim(data.name)=#{name}
方法2:将字段类型char()改为varchar2()类型。一般情况下,只有所有值长度都一样时才用char()类型,比如性别字段,用0表示男和1表示女时,就可以用char(1),如果值的长度不固定,有长有短,最好别用char()类型。
二、深入了解mybatis返回null
抛开mybatis框架,回到原始的jdbc查询,当使用oracle的char类型作为条件查询数据时,只有值完全一样时才能查到数据。
如创建一个测试表:
createtablet_user( user_namechar(5) ); insertintot_user(user_name)values('sgl');
select'"'||user_name||'"'from t_user;--查询结果为"sgl ",可以看出oracle自动补了两个空格
通过jdbc的PreparedStatement方式查询数据:
conn=getConnection(); ps=conn.prepareStatement("select*fromt_userwhereuser_name=?"); ps.setString(1,"sgl"); ResultSetrs=ps.executeQuery();
通过上面方式是无法查到数据的,因为查询条件值”sgl”和数据库中值”sgl“是不相等的。
如果值用“sgl”可以查到数据:
conn=getConnection(); ps=conn.prepareStatement("select*fromt_userwhereuser_name=?"); ps.setString(1,"sgl");--增加两个空格不足5位长度 ResultSetrs=ps.executeQuery();
如果使用trim()方式也可以查询到数据,如:
conn=getConnection(); ps=conn.prepareStatement("select*fromt_userwheretrim(user_name)=?");--先对数据库中user_name进行去空格,然后再比较 ps.setString(1,"sgl"); ResultSetrs=ps.executeQuery();
现在回到mybatis,同事的Mapper文件里查询sql如下:
select*fromdatawheredata.name=#{name}
main方法内容为:
publicstaticvoidmain(String[]args){ ApplicationContextctx=newClassPathXmlApplicationContext("applicationContext.xml"); DataServiced=(DataService)ctx.getBean("dataServiceImpl"); Datadata=d.selectByName("sgl"); System.out.println(data); }
其实,通过查看源码或将日志改为debug级别,可以看出在mybatis底层,会将查询语句使用PreparedStatement预编译,然后再将参数设置进去。如下面是mybatis打印出来的日志:
==>Preparing:select*fromdatawheredata.name=?
==>Parameters:sgl(String)
根据前面的jdbc查询,我们知道原因,所以很容易理解mybatis中的问题。
另外,mysql下面,当char类型字段的值不足时,好像并不自动将值以空格补足,尽管如此,当值长度不固定时,也不推荐使用char类型。
jdbc查询完整的代码如下:
jdbc工具类:
packagecom.songguoliang.url; importjava.sql.Connection; importjava.sql.DriverManager; importjava.sql.PreparedStatement; importjava.sql.ResultSet; importjava.sql.ResultSetMetaData; importjava.sql.SQLException; importjava.sql.Statement; importjava.util.ArrayList; importjava.util.List; importjava.util.ResourceBundle; /** *纯jdbc连接数据类 *@authorsgl * */ publicclassPureJdbcDao{ privatestaticResourceBundlebundle=ResourceBundle.getBundle("jdbc"); privatestaticintreCount=0; /** *获取连接 *@return */ privatestaticConnectiongetConnection(){ Connectionconn=null; try{ Class.forName(bundle.getString("driverClassName")); conn=DriverManager.getConnection(bundle.getString("url"), bundle.getString("username"),bundle.getString("password")); }catch(ClassNotFoundExceptione){ e.printStackTrace(); }catch(SQLExceptione){ e.printStackTrace(); }finally{ if(null==conn&&reCount<5){ try{ Thread.sleep(10000); }catch(InterruptedExceptione){ e.printStackTrace(); } reCount++; System.out.println("数据库第"+reCount+"次重连"); conn=getConnection(); } } returnconn; } /** *查询数据 *@paramsql *@return */ publicstaticListquery(Stringsql){ List result=newArrayList (); Connectionconn=null; Statementstmt=null; try{ //System.out.println("[PureJdbcDao]查询语句:"+sql); conn=getConnection(); stmt=conn.createStatement(); ResultSetrs=stmt.executeQuery(sql); ResultSetMetaDatarsMeta=rs.getMetaData(); while(rs.next()){ intcolumnNum=rsMeta.getColumnCount(); String[]field=newString[columnNum]; StringfieldValue=null; for(inti=1;i<=columnNum;i++){ fieldValue=rs.getString(i); if(fieldValue==null){ fieldValue=""; } field[i-1]=fieldValue; } result.add(field); } }catch(SQLExceptione){ e.printStackTrace(); }finally{ try{ if(stmt!=null){ stmt.close(); } if(conn!=null){ conn.close(); } }catch(SQLExceptione){ e.printStackTrace(); } } returnresult; } publicstaticList query(Stringsql,List params){ List result=newArrayList (); Connectionconn=null; PreparedStatementps=null; try{ conn=getConnection(); ps=conn.prepareStatement(sql); for(inti=0;i 测试类:
packagecom.songguoliang; importjava.util.Arrays; importjava.util.List; importcom.songguoliang.url.PureJdbcDao; publicclassTest{ publicstaticvoidmain(String[]args){ //Listlist=PureJdbcDao.query("select*fromt_userwhereuser_name=?",Arrays.asList("sgl"));//查询到条数:0 //List list=PureJdbcDao.query("select*fromt_userwhereuser_name=?",Arrays.asList("sgl"));//查询到条数:1 List list=PureJdbcDao.query("select*fromt_userwheretrim(user_name)=?",Arrays.asList("sgl"));//查询到条数:1 System.out.println("查询到条数:"+list.size()); } } 总结
以上所述是小编给大家介绍的解决mybatis使用char类型字段查询oracle数据库时结果返回null问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!