同事在學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
2
3
4
|
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方式查詢數據:
1
2
3
4
|
conn=getconnection(); ps=conn.preparestatement( "select * from t_user where user_name=?" ); ps.setstring( 1 , "sgl" ); resultset rs = ps.executequery(); |
通過上面方式是無法查到數據的,因為查詢條件值”sgl”和數據庫中值”sgl “是不相等的。
如果值用“sgl ”可以查到數據:
1
2
3
4
|
conn=getconnection(); ps=conn.preparestatement( "select * from t_user where user_name=?" ); ps.setstring( 1 , "sgl " ); -- 增加兩個空格不足 5 位長度 resultset rs = ps.executequery(); |
如果使用trim()方式也可以查詢到數據,如:
1
2
3
4
|
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如下:
1
2
3
|
<select id= "selectbyname" resulttype= "com.entity.data" parametertype= "java.lang.string" > select * from data where data.name=#{name} </select> |
main方法內容為:
1
2
3
4
5
6
7
|
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); } |
其實,通過查看源碼或將日志改為debug級別,可以看出在mybatis底層,會將查詢語句使用preparedstatement預編譯,然后再將參數設置進去。如下面是mybatis打印出來的日志:
==> preparing: select * from data where data.name=?
==> parameters: sgl(string)
根據前面的jdbc查詢,我們知道原因,所以很容易理解mybatis中的問題。
另外,mysql下面,當char類型字段的值不足時,好像并不自動將值以空格補足,盡管如此,當值長度不固定時,也不推薦使用char類型。
jdbc查詢完整的代碼如下:
jdbc工具類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
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 = 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( "數據庫第" +recount+ "次重連" ); conn = getconnection(); } } return conn; } /** * 查詢數據 * @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; } /** * 執行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(); } } } } |
測試類:
1
2
3
4
5
6
7
8
9
10
11
12
|
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問題,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:https://blog.csdn.net/u014344668/article/details/80664919