解决mybatis使用char类型字段查询oracle数据库时结果返回null问题

柔情只为你懂 2021-06-24 13:58 517阅读 0赞

同事在学mybatis时,遇到了一个问题就是,使用char类型字段作为查询条件时一直都查不出数据,其他类型的则可以。

使用的数据库是oracle,查询条件字段类型是char(50),java代码对应的是String类型。

后来经过排查,是由于在oracle中,char类型字段,如果内容长度不够,会自动以空格方式补足长度。如字段 name char(5),若值为sgl,那么oracle会自动用空格补足长度,最终值为sgl。

一、解决方法:

方法1:先用trim()函数把值去掉两边空格再作为条件查询,如:

  1. select * from data where data.name=#{name}

改为:

  1. select * from data where trim(data.name)=#{name}

方法2:将字段类型char()改为varchar2()类型。一般情况下,只有所有值长度都一样时才用char()类型,比如性别字段,用0表示男和1表示女时,就可以用char(1),如果值的长度不固定,有长有短,最好别用char()类型。

二、深入了解mybatis返回null

抛开mybatis框架,回到原始的jdbc查询,当使用oracle的char类型作为条件查询数据时,只有值完全一样时才能查到数据。

如创建一个测试表:

  1. create table t_user(
  2. user_name char(5)
  3. );
  4. insert into t_user (user_name)values('sgl');
  5. select '"'||user_name||'"' from t_user;

-- 查询结果为”sgl “,可以看出oracle自动补了两个空格

通过jdbc的PreparedStatement方式查询数据:

  1. conn=getConnection();
  2. ps=conn.prepareStatement("select * from t_user where user_name=?");
  3. ps.setString(1,"sgl");
  4. ResultSet rs = ps.executeQuery();

通过上面方式是无法查到数据的,因为查询条件值”sgl”和数据库中值”sgl “是不相等的。

如果值用“sgl ”可以查到数据:

  1. conn=getConnection();
  2. ps=conn.prepareStatement("select * from t_user where user_name=?");
  3. ps.setString(1,"sgl "); -- 增加两个空格不足5位长度
  4. ResultSet rs = ps.executeQuery();

如果使用trim()方式也可以查询到数据,如:

  1. conn=getConnection();
  2. ps=conn.prepareStatement("select * from t_user where trim(user_name)=?"); -- 先对数据库中user_name进行去空格,然后再比较
  3. ps.setString(1,"sgl");
  4. ResultSet rs = ps.executeQuery();

现在回到mybatis,同事的Mapper文件里查询sql如下:

  1. select * from data where data.name=#{name}

main方法内容为:

  1. public static void main(String[] args) {
  2. ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  3. DataService d = (DataService) ctx.getBean("dataServiceImpl");
  4. Data data = d.selectByName("sgl");
  5. System.out.println(data);
  6. }

其实,通过查看源码或将日志改为debug级别,可以看出在mybatis底层,会将查询语句使用PreparedStatement预编译,然后再将参数设置进去。如下面是mybatis打印出来的日志:

  1. ==> Preparing: select * from data where data.name=?
  2. ==> Parameters: sgl(String)

根据前面的jdbc查询,我们知道原因,所以很容易理解mybatis中的问题。

另外,mysql下面,当char类型字段的值不足时,好像并不自动将值以空格补足,尽管如此,当值长度不固定时,也不推荐使用char类型。

发表评论

表情:
评论列表 (有 0 条评论,517人围观)

还没有评论,来说两句吧...

相关阅读