解决mybatis使⽤char类型字段查询oracle数据库时结果返
回null问题
同事在学mybatis时,遇到了⼀个问题就是,使⽤char类型字段作为查询条件时⼀直都查不出数据,其他类型的则可以。
使⽤的数据库是oracle,查询条件字段类型是char(50),java代码对应的是String类型。
后来经过排查,是由于在oracle中,char类型字段,如果内容长度不够,会⾃动以空格⽅式补⾜长度。如字段 name
char(5),若值为sgl,那么oracle会⾃动⽤空格补⾜长度,最终值为sgl。
⼀、解决⽅法:
⽅法1:先⽤trim()函数把值去掉两边空格再作为条件查询,如:
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类型作为条件查询数据时,只有值完全⼀样时才能查到数据。
如创建⼀个测试表:
create table t_user(
user_name char(5)
);
insert into t_user (user_name)values('sgl');
select '"'||user_name||'"' from  t_user; -- 查询结果为"sgl  ",可以看出oracle⾃动补了两个空格
通过jdbc的PreparedStatement⽅式查询数据:
conn=getConnection();
ps=conn.prepareStatement("select * from t_user where user_name=?");
ps.setString(1,"sgl");
ResultSet rs = ps.executeQuery();
通过上⾯⽅式是⽆法查到数据的,因为查询条件值”sgl”和数据库中值”sgl “是不相等的。
如果值⽤“sgl ”可以查到数据:
conn=getConnection();
ps=conn.prepareStatement("select * from t_user where user_name=?");
ps.setString(1,"sgl "); -- 增加两个空格不⾜5位长度
ResultSet rs = ps.executeQuery();
如果使⽤trim()⽅式也可以查询到数据,如:
conn=getConnection();
ps=conn.prepareStatement("select * from t_user where trim(user_name)=?"); -- 先对数据库中user_name进⾏去空格,然后再⽐较
ps.setString(1,"sgl");
ResultSet rs = ps.executeQuery();
现在回到mybatis,同事的Mapper⽂件⾥查询sql如下:
<select id="selectByName" resultType="ity.Data" parameterType="java.lang.String">
select * from data where data.name=#{name}
</select>
main⽅法内容为:
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("l");
DataService d = (DataService) Bean("dataServiceImpl");
Data data = d.selectByName("sgl");
System.out.println(data);
}
其实,通过查看源码或将⽇志改为debug级别,可以看出在mybatis底层,会将查询语句使⽤PreparedStatement预编译,然后再将参数设置进去。如下⾯是mybatis打印出来的⽇志:
==> Preparing: select * from data where data.name=?
==> Parameters: sgl(String)
根据前⾯的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连接数据类
* @author sgl
*
*/
public class PureJdbcDao {
private static ResourceBundle bundle = Bundle("jdbc");
private static int reCount = 0;
/
**
* 获取连接
* @return
*/
private static Connection getConnection(){
Connection conn=null;
try {
Class.String("driverClassName"));
conn = String("url") ,
} 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("数据库第"+reCount+"次重连");
conn = getConnection();
}
}
return conn;
}jdbc连接oracle
/**
* 查询数据
* @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 = ateStatement();
ResultSet rs = uteQuery(sql);
ResultSetMetaData rsMeta = rs.getMetaData();
()){
int ColumnCount();
String []field=new String[columnNum];
String fieldValue=null;
for(int i=1;i<=columnNum;i++){
String(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+(i));
}
ResultSet rs = ps.executeQuery();
ResultSetMetaData rsMeta = rs.getMetaData();
()){
int ColumnCount();
String []field=new String[columnNum];
String fieldValue=null;
for(int i=1;i<=columnNum;i++){
String(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;
}
/**
* 执⾏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 = ateStatement();
connmit();
} catch (SQLException e) {
try {
} 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")); // 查询到条数:0
//List<String[]>list=PureJdbcDao.query("select * from t_user where user_name=?",Arrays.asList("sgl ")); //查询到条数:1
List<String[]>list=PureJdbcDao.query("select * from t_user where trim(user_name)=?",Arrays.asList("sgl")); //查询到条数:1
System.out.println("查询到条数:"+list.size());
}
}
总结
以上所述是⼩编给⼤家介绍的解决mybatis使⽤char类型字段查询oracle数据库时结果返回null问题,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。在此也⾮常感谢⼤家对⽹站的⽀持!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。