在使用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. css超出隐藏显示省略号怎么设置?

    当我们在进行网页前端开发的时候,一般获取文章标题,然后一行一行的显示.但是当标题过长的时候,就会造成换行显示.还有显示部分文本信息时,如果全部显示就过于繁琐,会带来不会的网页体验感.虽然我们可以使用o ...

  2. FastAPI 学习之路(十九)处理错误

    系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...

  3. 一文彻底搞通TCP之send & recv原理

    接触过网络开发的人,大抵都知道,上层应用使用send函数发送数据,使用recv来接收数据,而send和recv的实现原理又是怎样的呢? 在前面的几篇文章中,我们有提过,TCP是个可靠的.全双工协议.其 ...

  4. 【java】【作业】定义课程信息;继承和组合练习

    问题: 定义课程信息类,包含课程编号.课程名称及学生成绩.编程实现对软件工程专业的某班级的所有课程成绩统计,包括平均成绩.最高成绩.最低成绩,并打印成绩等级分布律. 分析 初分析: 父类(课程信息类) ...

  5. python常用内置函数(转载)

    1. 和数字相关 1.1 数据类型 1.2 进制转换 1.3 数学运算 2. 和数据结构相关 2.1 序列 2.2 数据集合 2.3 相关内置函数 3. 和作用域相关 4. 和迭代器生成器相关 5. ...

  6. SpringCloud-初见

    目录 前言 微服务概述 微服务与微服务架构 微服务优缺点 微服务技术栈 为什么选择SpringCloud作为微服务架构 SpringCloud入门 SpringCloud和SpringBoot的关系 ...

  7. mongodb的索引操作

    在mongodb中,当我们一个集合中的数据量非常大时,比如几百万条数据,如果不使用索引,对数据的查询就会进行全表扫描,这个时候查询的速度就会非常的慢,此时我们就需要为集合建立上索引,从而加快查询的速度 ...

  8. Noip模拟52 2021.9.13

    T1 异或 比较稳的切掉 观察数据范围,无法线性筛啥的,根号复杂度也会死,于是只能考虑$log$级 然后打表 发现当$n$为$2^i$时的答案是一个可递归数列: $1,3,7,15,31,63,127 ...

  9. Balance的数学思想构造辅助函数

    本类题的证明难点便在于如何构造出满足答案的辅助函数.通过下列类题便可以很好的理解. 题一 该类题可以理解为积分内部f(x)与xf(x)处于一种失衡状态,故我们需要使其平衡,否则直接构造出的函数无法满足 ...

  10. QT判断文件/目录是否存在

    最近在用qt写一个ui,遇到删除sd卡中的文件失败情况,有些时候是存在删除链表里面的文件在sd卡上已经不存在了,导致失败,以为我的链表是定时刷新的,但是文件是实时更新会同步覆盖的.这样就存在可能上一秒 ...