- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章利用JDBC的PrepareStatement打印真实SQL的方法详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
本文主要给大家介绍了关于利用JDBC的PrepareStatement打印真实SQL的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍:
我们知道,JDBC 的 PrepareStatement 优点多多,通常都是推荐使用 PrepareStatement 而不是其基类 Statment。PrepareStatement 支持 ? 占位符,可以将参数按照类型转自动换为真实的值。既然这一过程是自动的,封装在 JDBC 内部的,那么我们外部就不得而知目标的 SQL 最终生成怎么样——于是在调试过程中便有一个打印 SQL 的问题。我们对 PrepareStatement 传入 SQL 语句,如 SELECT * FROM table WHERE id = ?,然后我们传入对应的 id 参数,假设是 id = 10,那怎么把得到参数的 SELECT * FROM table WHERE id = 12 结果完整地得出来呢?——这便是本文所要探讨的问题。下面话不多说了,来一起看看详细的介绍:
方法如下:
首先,我们看看典型的一个 PrepareStatement 调用方法,如下一个函数, 。
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
|
/**
* 查询单个结果,保存为 Map<String, Object> 结构。如果查询不到任何数据返回 null。
*
* @param conn
* 数据库连接对象
* @param sql
* SQL 语句,可以带有 ? 的占位符
* @param params
* 插入到 SQL 中的参数,可单个可多个可不填
* @return Map<String, Object> 结构的结果。如果查询不到任何数据返回 null。
*/
public
static
Map<String, Object> query(Connection conn, String sql, Object... params) {
Map<String, Object> map =
null
;
printRealSql(sql, params);
// 打印真实 SQL 的函数
try
(PreparedStatement ps = conn.prepareStatement(sql);) {
if
(params !=
null
)
for
(
int
i =
0
; i < params.length; i++)
ps.setObject(i +
1
, params[i]);
try
(ResultSet rs = ps.executeQuery();) {
if
(rs.isBeforeFirst()) {
map = getResultMap(rs);
}
else
{
LOGGER.info(
"查询 SQL:{0} 没有符合的记录!"
, sql);
}
}
}
catch
(SQLException e) {
LOGGER.warning(e);
}
return
map;
}
|
值得注意该函数里面:
1
|
printRealSql(sql, params);
// 打印真实 SQL 的函数
|
其参数一 sql 就是类似 SELECT * FROM table WHERE id = ? 的语句,参数二 params 为 Object... params 的参数列表,可以是任意类似的合法 SQL 值。最后,通过 printRealSql 函数最终得出形如 SELECT * FROM table WHERE id = 12 的结果.
printRealSql 函数源码如下:
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
|
/**
* 在开发过程,SQL语句有可能写错,如果能把运行时出错的 SQL 语句直接打印出来,那对排错非常方便,因为其可以直接拷贝到数据库客户端进行调试。
*
* @param sql
* SQL 语句,可以带有 ? 的占位符
* @param params
* 插入到 SQL 中的参数,可单个可多个可不填
* @return 实际 sql 语句
*/
public
static
String printRealSql(String sql, Object[] params) {
if
(params ==
null
|| params.length ==
0
) {
LOGGER.info(
"The SQL is------------>\n"
+ sql);
return
sql;
}
if
(!match(sql, params)) {
LOGGER.info(
"SQL 语句中的占位符与参数个数不匹配。SQL:"
+ sql);
return
null
;
}
int
cols = params.length;
Object[] values =
new
Object[cols];
System.arraycopy(params,
0
, values,
0
, cols);
for
(
int
i =
0
; i < cols; i++) {
Object value = values[i];
if
(value
instanceof
Date) {
values[i] =
"'"
+ value +
"'"
;
}
else
if
(value
instanceof
String) {
values[i] =
"'"
+ value +
"'"
;
}
else
if
(value
instanceof
Boolean) {
values[i] = (Boolean) value ?
1
:
0
;
}
}
String statement = String.format(sql.replaceAll(
"\\?"
,
"%s"
), values);
LOGGER.info(
"The SQL is------------>\n"
+ statement);
ConnectionMgr.addSql(statement);
// 用来保存日志
return
statement;
}
/**
* ? 和参数的实际个数是否匹配
*
* @param sql
* SQL 语句,可以带有 ? 的占位符
* @param params
* 插入到 SQL 中的参数,可单个可多个可不填
* @return true 表示为 ? 和参数的实际个数匹配
*/
private
static
boolean
match(String sql, Object[] params) {
if
(params ==
null
|| params.length ==
0
)
return
true
;
// 没有参数,完整输出
Matcher m = Pattern.compile(
"(\\?)"
).matcher(sql);
int
count =
0
;
while
(m.find()) {
count++;
}
return
count == params.length;
}
|
可见,上述思路是非常简单的,——有多少个 ? 占位符,就要求有多少个参数,然后一一对照填入(数组)。match 函数会检查第一个步骤,检查个数是否匹配,否则会返回“SQL 语句中的占位符与参数个数不匹配”的提示;然后,参数的值会被转换为符合 SQL 值所要求的类型;最后,就是将 SQL 一一填入,——此处使用了一个字符串的技巧,先把 ? 字符通通转换为 %s,——那是 String.format 可识别的占位符,如此再传入 Object[] 参数列表,即可得出我们期待的 SQL 结果.
我们不能保证那 SQL 可以直接放到数据库中被解析。因为我们的初衷只是把 SQL 打印出来,务求更近一步让程序员在开发阶段看到 SQL 是怎么样子的,而且不是一堆 ?、?……,这样会显得更符合真实情形一点.
PrepareStatement 内部源码肯定有这一步骤或者某个变量是表示那个真实 SQL 的,——只是没有暴露出来。如果有,那么对程序员会更友好一些.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我的支持.
原文链接:http://blog.csdn.net/zhangxin09/article/details/70187712 。
最后此篇关于利用JDBC的PrepareStatement打印真实SQL的方法详解的文章就讲到这里了,如果你想了解更多关于利用JDBC的PrepareStatement打印真实SQL的方法详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在寻找x86 Assembly中pow(real, real)的实现。我也想了解算法的工作原理。 最佳答案 只需将其计算为2^(y*log2(x))即可。 有一个x86指令FYL2X计算y *
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
风格指南的最后一点 http://www.python.org/dev/peps/pep-0008 读... 不要使用 == 将 bool 值与 True 或 False 进行比较。 为什么? 编辑只
我似乎无法完成这件事。我仍然在我的日志中看到 cloudflare IP。目前,我有一个负载均衡器,它位于 Cloudflare 后面。 目前,这是与 forwardfor 相关的块: opt
此代码行选择任何类名不是“id”和“quantity”的 div 内的所有子输入:: $("div.item > div:not(.id,.quantity) > :input").live("key
我在测试真实产品时遇到错误。当我单击购买按钮时,出现错误“此版本的应用程序未配置为市场计费”。 我用这个例子https://github.com/robotmedia/AndroidBillingLi
到目前为止我能找到的所有答案都建议调用 omp_set_num_threads。虽然在大多数情况下这是一个正确的答案,但它对我不起作用。在内部,调用 omp_set_num_threads 会导致创建
假设我有 3 个显示器。如何仅通过其索引获取第二个句柄? EnumDisplayMonitors() 不会工作,因为它也枚举了伪设备,而 EnumDisplayDevices() 没有给我句柄。 最佳
我一直在尝试制作一个简单的小游戏来测试我的逻辑,这是一个简单的迷宫,它很丑,而且到目前为止很糟糕。 引擎工作得很好,考虑到迷宫已经存在(矩阵),它甚至可以愉快,但我无意绘制一堆 map ,这可能是在
Cloudflare 代理包含一个名为 CF-Connecting-IP 的 header 和用户的真实 IP。我想让 traefik 读取这个 header 并用它的内容创建一个 X-Real-Ip
我想要上下文菜单中的不同菜单项,具体取决于我在 JTable 中单击的行 大多数示例并没有真正显示上下文菜单(应该根据上下文 - 所选行进行填充) 我尝试过这个: popupMenu = ne
我有一个对象 callInst。如何获取函数的真实名称而不是 IR 代码中的名称?如果我在我的通行证中运行此代码(Useless 在另一个问题中发布) StringRef get_function_n
我在 Appium 和 iPad 2 上使用了以下所需的功能 DesiredCapabilities capabilities = new DesiredCapabilities(); capabil
根据documentation 我们可以通过以下方式在模拟器上运行我们的 android 项目: cordova 运行 android 或 cordova emulate android 但是如何在真
在 ASP.NET 中,有没有办法获得真正的原始 URL? 例如,如果用户浏览到“http://example.com/mypage.aspx/%2F”,我希望能够获得“http://example.
我的 NSInputStream 遇到问题。这是我的代码: case NSStreamEventHasBytesAvailable: printf("BYTE AVAILABLE\n"
$(selector).click() 结果没有任何反应。 this answer在浏览器控制台中工作,javascript 上下文设置为 iframe,但不是主页: simulateMouseCli
我在我的 AB Micro820 PLC 中设置了 modbus 映射。我在 40001 中有一个数组用于写入,在 42001 中有一个数组用于读取。两者都是 200 个元素和 REAL 类型(32
我正在寻找有关设计契约(Contract)管理数据模型的建议。因此,合约的一般生命周期是: 契约(Contract)已创建并处于“草稿”状态。它可以在内部查看,并且可以进行更改。 契约(Contrac
我正在尝试让我的 WebView fullscreen 达到标准,我知道如何将它拉伸(stretch)到“全屏”,但我想做的是当您长按 WebView 并选择全屏选项时,创建全屏。有谁知道该怎么做?
我是一名优秀的程序员,十分优秀!