在使用Mybatis过程中,你可以体会到它的强大与灵活之处,由衷的为Mybatis之父点上999个赞!在使用过程中经常会遇到这样一种情况,我查询数据的时候,表名称是动态的从程序中传入的,比如我们通过mybatis的xml文件写sql查询时都是下面的样子:
1、正常的查询

1
2
3
<select id="activityEnrollModelTableName" parameterType="java.util.HashMap" resultType="java.util.HashMap">
SELECT * FROM user WHERE userid = #
</select>

上面的查询语句用mybatis执行时,其实是自动的按照JDBC的预编译语句方式执行的,等同于下面一段JDBC代码的执行过程

1
2
3
4
5
6
7
8
9
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManage.getConnection("jdbc:mysql://localhost:3306/dbname","root","112233");
PreparedStatement preState = conn.prepareStatement("SELECT * FROM user WHERE userid = ?");
preState.setString(1,"96");
ResultSet result = preState.executeQuery();
while(result.next()){
result.getString(columnname);
..........
}

到这里我们不禁疑惑,难道mybatis默认都是按照预编译语句的方式执行sql的吗?其实就是这样。通过查看mybatis官网文档可以看到有这么一个参数,statementType=[STATEMENT | PREPARED | CALLABLE ];有三个可选值,mybatis默认值是PREPARED;
这个参数是什么作用呢:

  1. 设定mybatis执行sql的模式
  2. STATEMENT设定为非预编译语句模式
  3. PREPARED设定为预编译语句模式–mybatis默认
  4. CALLABLE设定为兼容模式,或者自适应模式,比如设置该值后,mybatis处理sql时会自动的处理根据#、$去判断处理,后面说一下#和$的区别。

综上所述,mybatis默认按照预编译语句方式执行sql语句

2、动态传入表名

其实也经常会遇到动态的传入tableName的情况,也就是说上面的sql语句中的”user”是动态传入的,动态传入表名是mybatis中的一种特殊情况,

1
2
3
<select id="activityEnrollModelTableName" parameterType="java.util.HashMap" resultType="java.util.HashMap">
SELECT * FROM # WHERE userid = # //错误的写法
</select>

针对上面的语句,如果让mybatis仍然按照预编译语句方式执行时,等同于如下面的JDBC代码:

1
2
3
4
5
6
7
8
9
10
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManage.getConnection("jdbc:mysql://localhost:3306/dbname","root","112233");
PreparedStatement preState = conn.prepareStatement("SELECT * FROM ? WHERE userid = ?");
preState.setString(1,"USER");
preState.setString(2,"96");
ResultSet result = preState.executeQuery();
while(result.next()){
result.getString(columnname);
..........
}

我们把该段JDBC代码通过java代码执行后,发现会报异常:

1
java.sql.SQLException: ORA-00903: 表名无效

所以可以说明预编译语句不能用于列名(查询的列名也不能用预编译语句)、表名;只能作用与where条件参数属性!既然JDBC就不能将预编译语句方式作用与表名上面,那么mybatis就同样也行不通(因为mybatis默认是预编译语句模式)。不过mybatis也早已考虑到了这种情况,所以为我们做了处理:

  1. select标签语句中添加statementType=”STATEMENT”的属性配置
  2. 标签内的sql语句中将所有的${}更换成为#{},即将$还成#;
    1
    2
    3
    <select id="activityEnrollModelTableName" statementType="STATEMENT" parameterType="java.util.HashMap" resultType="java.util.HashMap">
    SELECT * FROM $ WHERE userid = $ //正确的写法
    </select>

上面的语句标签中通过添加statementType=”STATEMENT”配置后,mybatis就不再使用预编译语句方式执行sql语句了,也就是通过直接执行sql语句操作;那么既然添加了statementType=”STATEMENT”非预编译配置后,为什么还需要把#换成$呢?其实是这样:

    1. “#” 是预编译语句模式下面的默认匹配符,也就是说mybatis遇到#{}时,将#替换成占位符?;被解析为一个JDBC预编译语句,然后再将#本身的值set进来。
    2. “$” 是非预编译语句下面的匹配符,非预编译语句说白了就是你传入什么sql语句,就执行什么sql语句,mybatis不做任何处理操作,但是这里mybatis会将${}对应的值,当做一个字符串处理,也就是说你程序接口方法中传递过来参数值是什么,对应的sql填充就是什么!

Mybatis动态传入tableName--非预编译(STATEMENT)的更多相关文章

  1. mybatis中预编译sql与非预编译sql

    预编译sql有缓存作用,非预编译没得 mybaits中带有#传参的有预编译左右,$没得 多用#传参 预编译语句的优势在于归纳为:一次编译.多次运行,省去了解析优化等过程:此外预编译语句能防止sql注入 ...

  2. [转]MyBatis动态传入表名、字段名参数的解决办法

    一直在使用Mybatis这个ORM框架,都是使用mybatis里的一些常用功能.今天在项目开发中有个业务是需要限制各个用户对某些表里的字段查询以及某些字段是否显示,如某张表的某些字段不让用户查询到.这 ...

  3. MyBatis动态传入表名

    mybatis里#{}与${}的用法: 在动态sql解析过程,#{}与${}的效果是不一样的: #{ } 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符. 如以下 ...

  4. MyBatis动态传入表名,字段名参数的解决办法---statementType用法

    statementType="STATEMENT" 要实现动态传入表名.列名,需要做如下修改 添加属性statementType="STATEMENT" 同时s ...

  5. MyBatis动态传入表名,字段名参数的解决办法

    原文:http://blog.csdn.net/xichenguan/article/details/50393748 要实现动态传入表名.列名,需要做如下修改 添加属性statementType=& ...

  6. mybatis动态传入表名、列名

    原文:http://luoyu-ds.iteye.com/blog/1517607 要实现动态传入表名.列名,需要做如下修改 添加属性statementType=”STATEMENT” (可省略) 同 ...

  7. oracle学习笔记(七) 预编译Statement介绍与使用

    预编译Statement优点 执行效率高 由于预编译语句使用占位符 "?",在执行SQL之前语句会被先发送到Oracle服务器进行语法检查和编译等工作,并将SQL语句加入到Orac ...

  8. JDBC预编译statement(preparedstatement)和statement的比较、execute与executeUpdate的区别

    和 Statement一样,PreparedStatement也是用来执行sql语句的与创建Statement不同的是,需要根据sql语句创建PreparedStatement除此之外,还能够通过设置 ...

  9. MyBatis,动态传入表名,字段名的解决办法

    转载:http://luoyu-ds.iteye.com/blog/1517607 今天做项目,遇到的问题就是需求修改数据表的记录,而且字段名都不是固定的,也就是说是需要通过参数传入的, 本来这也不是 ...

随机推荐

  1. 记录一次基于VuePress + Github 搭建个人博客

    最终效果图 网站:https://chandler712.github.io/ 一.前言 VuePress 是尤雨溪推出的支持 Vue 及其子项目的文档需求而写的一个项目,UI简洁大方,官方文档详细容 ...

  2. 题解「BZOJ4310」跳蚤

    题目传送门 Description 现在有一个长度为 \(n\) 的字符串,将其划分为 \(k\) 段,使得这 \(k\) 段每一段的字典序最大子串中字典序最大的字符串字典序尽量小.求出这个字符串. ...

  3. Kubernetes List-Watch 机制原理与实现 - chunked

    概述http chunkedwatch api 概述 Kubernetes 中主要通过 List-Watch 机制实现组件间的异步消息通信,List-Watch 机制的实现原理值得深入分析下 . 在 ...

  4. selenium3 利用cookie实现免登陆

    1.首先访问要操作的页面 2.登陆一次,使用Fiddle等工具抓取出cookie 3.按照如下代码,即可成功登陆 from selenium import webdriver url = " ...

  5. vue基础-组件&插槽

    组件 组件化的意义:封装(复用,把逻辑隐藏起来,提高可维护性),快速开发(搭积木) 约定:我们通常把那些除了HTML标签以外的自定义组件,才称为'组件',结论是,我们说"父组件"& ...

  6. 第二次Alpha Scrum Meeting

    本次会议为Alpha阶段第二次Scrum Meeting会议 会议概要 会议时间:2021年4月24日 会议地点:线上会议 会议时长:30min 会议内容简介:本次会议主要由每个人展示自己目前完成的工 ...

  7. UltraSoft Scrum Meeting 博客汇总

    一.Alpha阶段 UltraSoft - Alpha - Scrum Meeting 1 UltraSoft - Alpha - Scrum Meeting 2 UltraSoft - Alpha ...

  8. Taylor公式原来可以这么简单

    1.Taylor公式 解决:含有高阶导数的中值定理或定积分.极限运算等题目 条件:f(x)在x=x0领域内(n+1)阶可导 结论:f(x)=Pn(x)+Rn(x) 2.x和x0的取值 3.Taylor ...

  9. 最后的OI(HAOI2020游记)

    马上就省选了,怎么不得写点什么?要不然到最后或许就真的落得个白茫茫大地真干净的局面. 其实也不知道该说啥?我这一路走来,感觉挺赚的. 每一个OIer背后都有一个故事,所以,我有故事,你有酒吗? 依稀记 ...

  10. ubuntn 一直循环登录界面 (卸载nvidia驱动)

    由于在Ubuntu下安装了Nvidia显卡驱动后开机一直处于循环登录界面,密码输入正确也是进不去,然后就决定卸载Nvidia显卡驱动.首先是在能使用tty1登录的情况下,使用 $ sudo apt-g ...