解決mybatis使用char類型字段查詢oracle數(shù)據(jù)庫時結(jié)果返回null問題

同事在學mybatis時,遇到了一個問題就是,使用char類型字段作為查詢條件時一直都查不出數(shù)據(jù),其他類型的則可以。

站在用戶的角度思考問題,與客戶深入溝通,找到和平網(wǎng)站設(shè)計與和平網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站制作、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、空間域名、虛擬主機、企業(yè)郵箱。業(yè)務覆蓋和平地區(qū)。

 使用的數(shù)據(jù)庫是oracle,查詢條件字段類型是char(50),java代碼對應的是String類型。

 后來經(jīng)過排查,是由于在oracle中,char類型字段,如果內(nèi)容長度不夠,會自動以空格方式補足長度。如字段 name char(5),若值為sgl,那么oracle會自動用空格補足長度,最終值為sgl。

一、解決方法:

 方法1:先用trim()函數(shù)把值去掉兩邊空格再作為條件查詢,如:

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

改為:

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

方法2:將字段類型char()改為varchar2()類型。一般情況下,只有所有值長度都一樣時才用char()類型,比如性別字段,用0表示男和1表示女時,就可以用char(1),如果值的長度不固定,有長有短,最好別用char()類型。

二、深入了解mybatis返回null

拋開mybatis框架,回到原始的jdbc查詢,當使用oracle的char類型作為條件查詢數(shù)據(jù)時,只有值完全一樣時才能查到數(shù)據(jù)。

 如創(chuàng)建一個測試表:

create table t_user(
    user_name char(5)
);
insert into t_user (user_name)values('sgl');

select '"'||user_name||'"' from  t_user; -- 查詢結(jié)果為"sgl  ",可以看出oracle自動補了兩個空格

通過jdbc的PreparedStatement方式查詢數(shù)據(jù):

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

通過上面方式是無法查到數(shù)據(jù)的,因為查詢條件值”sgl”和數(shù)據(jù)庫中值”sgl “是不相等的。

 如果值用“sgl ”可以查到數(shù)據(jù):

conn=getConnection();
ps=conn.prepareStatement("select * from t_user where user_name=?");
ps.setString(1,"sgl "); -- 增加兩個空格不足5位長度
ResultSet rs = ps.executeQuery();

如果使用trim()方式也可以查詢到數(shù)據(jù),如:

conn=getConnection();
ps=conn.prepareStatement("select * from t_user where trim(user_name)=?"); -- 先對數(shù)據(jù)庫中user_name進行去空格,然后再比較
ps.setString(1,"sgl");
ResultSet rs = ps.executeQuery();

現(xiàn)在回到mybatis,同事的Mapper文件里查詢sql如下:

<select id="selectByName" resultType="com.entity.Data" parameterType="java.lang.String">
 select * from data where data.name=#{name}
</select>

main方法內(nèi)容為:

public static void main(String[] args) {
  ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  DataService d = (DataService) ctx.getBean("dataServiceImpl");

  Data data = d.selectByName("sgl");
  System.out.println(data);
}

其實,通過查看源碼或?qū)⑷罩靖臑閐ebug級別,可以看出在mybatis底層,會將查詢語句使用PreparedStatement預編譯,然后再將參數(shù)設(shè)置進去。如下面是mybatis打印出來的日志:

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

根據(jù)前面的jdbc查詢,我們知道原因,所以很容易理解mybatis中的問題。

另外,MySQL下面,當char類型字段的值不足時,好像并不自動將值以空格補足,盡管如此,當值長度不固定時,也不推薦使用char類型。

jdbc查詢完整的代碼如下:

jdbc工具類:

package com.songguoliang.url;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
/**
 * 純jdbc連接數(shù)據(jù)類
 * @author sgl
 *
 */
public class PureJdbcDao {
  private static ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
  private static int reCount = 0;
  /**
   * 獲取連接
   * @return
   */
  private static Connection getConnection(){
    Connection conn=null;
    try {
      Class.forName(bundle.getString("driverClassName"));
      conn = DriverManager.getConnection(bundle.getString("url") ,
          bundle.getString("username") , bundle.getString("password"));
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (SQLException e) {
      e.printStackTrace();
    }finally{
      if(null==conn&&reCount<5){
        try {
          Thread.sleep(10000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        reCount++;
        System.out.println("數(shù)據(jù)庫第"+reCount+"次重連");
        conn = getConnection();
      }
    }
    return conn;
  }
  /**
   * 查詢數(shù)據(jù)
   * @param sql
   * @return
   */
  public static List<String[]>query(String sql){
    List<String[]>result=new ArrayList<String[]>();
    Connection conn=null;
    Statement stmt=null;
    try {
      //System.out.println("[PureJdbcDao]查詢語句:" + sql);
      conn=getConnection();
      stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery(sql);
      ResultSetMetaData rsMeta = rs.getMetaData();
      while(rs.next()){
        int columnNum=rsMeta.getColumnCount();
        String []field=new String[columnNum];
        String fieldValue=null;
        for(int i=1;i<=columnNum;i++){
          fieldValue=rs.getString(i);
          if(fieldValue==null){
            fieldValue="";
          }
          field[i-1]=fieldValue;
        }
        result.add(field);
      }
    } catch (SQLException e) {
      e.printStackTrace();
    }finally{
      try {
        if(stmt!=null){
          stmt.close();
        }
        if(conn!=null){
          conn.close();
        }
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    return result;
  }
  public static List<String[]>query(String sql,List<String>params){
    List<String[]>result=new ArrayList<String[]>();
    Connection conn=null;
    PreparedStatement ps=null;
    try {
      conn=getConnection();
      ps=conn.prepareStatement(sql);
      for(int i=0;i<params.size();i++){
        ps.setString(i+1,params.get(i));
      }
      ResultSet rs = ps.executeQuery();
      ResultSetMetaData rsMeta = rs.getMetaData();
      while(rs.next()){
        int columnNum=rsMeta.getColumnCount();
        String []field=new String[columnNum];
        String fieldValue=null;
        for(int i=1;i<=columnNum;i++){
          fieldValue=rs.getString(i);
          if(fieldValue==null){
            fieldValue="";
          }
          field[i-1]=fieldValue;
        }
        result.add(field);
      }
    } catch (SQLException e) {
      e.printStackTrace();
    }finally{
      try {
        if(ps!=null){
          ps.close();
        }
        if(conn!=null){
          conn.close();
        }
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    return result;
  }
  /**
   * 執(zhí)行sql語句
   * @param sql
   */
  public static void execute(String sql){
    Connection conn=null;
    Statement stmt=null;
    try {
      //System.out.println("[PureJdbcDao]sql語句:" + sql);
      conn = getConnection();
      conn.setAutoCommit(false);
      stmt = conn.createStatement();
      stmt.execute(sql);
      conn.commit();
    } catch (SQLException e) {
      try {
        conn.rollback();
      } catch (SQLException e1) {
        e1.printStackTrace();
      }
      e.printStackTrace();
    }finally{
      try {
        if(stmt!=null){
          stmt.close();
        }
        if(conn!=null){
          conn.close();
        }
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
}

測試類:

package com.songguoliang;
import java.util.Arrays;
import java.util.List;
import com.songguoliang.url.PureJdbcDao;
public class Test {
  public static void main(String[] args) {
    //List<String[]>list=PureJdbcDao.query("select * from t_user where user_name=?",Arrays.asList("sgl")); // 查詢到條數(shù):0
    //List<String[]>list=PureJdbcDao.query("select * from t_user where user_name=?",Arrays.asList("sgl ")); //查詢到條數(shù):1
    List<String[]>list=PureJdbcDao.query("select * from t_user where trim(user_name)=?",Arrays.asList("sgl")); //查詢到條數(shù):1
    System.out.println("查詢到條數(shù):"+list.size());
  }
}

總結(jié)

以上所述是小編給大家介紹的解決mybatis使用char類型字段查詢oracle數(shù)據(jù)庫時結(jié)果返回null問題,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對創(chuàng)新互聯(lián)網(wǎng)站的支持!

網(wǎng)站題目:解決mybatis使用char類型字段查詢oracle數(shù)據(jù)庫時結(jié)果返回null問題
文章出自:http://muchs.cn/article4/pidoie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、、網(wǎng)站營銷、服務器托管、響應式網(wǎng)站、定制開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化