- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章解决mybatis使用char类型字段查询oracle数据库时结果返回null问题由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
同事在学mybatis时,遇到了一个问题就是,使用char类型字段作为查询条件时一直都查不出数据,其他类型的则可以.
使用的数据库是oracle,查询条件字段类型是char(50),java代码对应的是string类型.
后来经过排查,是由于在oracle中,char类型字段,如果内容长度不够,会自动以空格方式补足长度。如字段 name char(5),若值为sgl,那么oracle会自动用空格补足长度,最终值为sgl.
1、解决方法:
方法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()类型.
2、深入了解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 。
最后此篇关于解决mybatis使用char类型字段查询oracle数据库时结果返回null问题的文章就讲到这里了,如果你想了解更多关于解决mybatis使用char类型字段查询oracle数据库时结果返回null问题的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!