mybatis中支持mysql中的变量吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis中支持mysql中的变量吗?相关的知识,希望对你有一定的参考价值。

@rownum这样的变量是写在sql里面的不是存储过程里面,在mybatis的mapper.xml里面,应该怎么写?
加了CDATA也不行

mysql连接url + allowMultiQueries=true

jdbc:mysql://localhost:3306/DBS?allowMultiQueries=true

MyBatis MySql -Stack Overflow

参考技术A 以前Mysql官方网站上有一个图形软件叫“MySQL GUI Tools”,它里面有一个工具“MySQLMigrationTool”就是干这个活的。
MySQL GUI Tools现在的oracle官方网站上已经找不到了,但它很有名,其它一些网站上也有下的。
参考技术B 支持
SET @ROW_NUMBER:=0,@median_group:='';
SELECT
<if test="intervalTime == 'day' ">
a.year,a.month,a.day,
</if>
<if test="intervalTime == 'month' ">
a.year,a.month,
</if>
<if test="intervalTime == 'year' ">
a.year,
</if>
ROUND(AVG(avgResponseTime)) AS median
FROM(
SELECT @ROW_NUMBER:=CASE
<if test="intervalTime == 'day' ">
WHEN @median_group = a.day
</if>
<if test="intervalTime == 'month' ">
WHEN @median_group = a.month
</if>
<if test="intervalTime == 'year' ">
WHEN @median_group = a.year
</if>
THEN @ROW_NUMBER + 1
ELSE 1
END AS count_of_group,
<if test="intervalTime == 'day' ">
@median_group:=a.day AS median_group,
</if>
<if test="intervalTime == 'month' ">
@median_group:=a.month AS median_group,
</if>
<if test="intervalTime == 'year' ">
@median_group:=a.year AS median_group,
</if>
a.*,b.total_of_group
FROM (
SELECT a.year,a.month,a.day,a.avgResponseTime
FROM analysis_base_service_invoke_by_hour AS a
WHERE createTime BETWEEN #startTime AND #endTime
AND deleteFlag=0
AND serviceId=#serviceId
<if test="userId != null">
AND userId=#userId
</if>
<if test="intervalTime == 'day' ">
ORDER BY a.year,a.month,a.day,a.avgResponseTime ASC
</if>
<if test="intervalTime == 'month' ">
ORDER BY a.year,a.month,a.avgResponseTime ASC
</if>
<if test="intervalTime == 'year' ">
ORDER BY a.year,a.avgResponseTime ASC
</if>
) AS a,
(
SELECT COUNT(*) AS total_of_group,a.year,a.month,a.day FROM(
SELECT a.year,a.month,a.day,a.avgResponseTime
FROM analysis_base_service_invoke_by_hour AS a
WHERE createTime BETWEEN #startTime AND #endTime
AND deleteFlag=0
AND serviceId=#serviceId
<if test="userId != null">
AND userId=#userId
</if>
<if test="intervalTime == 'day' ">
ORDER BY a.year,a.month,a.day,a.avgResponseTime ASC
</if>
<if test="intervalTime == 'month' ">
ORDER BY a.year,a.month,a.avgResponseTime ASC
</if>
<if test="intervalTime == 'year' ">
ORDER BY a.year,a.avgResponseTime ASC
</if>
) AS a
<if test="intervalTime == 'day' ">
GROUP BY a.year,a.month,a.day
</if>
<if test="intervalTime == 'month' ">
GROUP BY a.year,a.month
</if>
<if test="intervalTime == 'year' ">
GROUP BY a.year
</if>
) AS b
<if test="intervalTime == 'day' ">
WHERE a.year=b.year AND a.month=b.month AND a.day=b.day
</if>
<if test="intervalTime == 'month' ">
WHERE a.year=b.year AND a.month=b.month
</if>
<if test="intervalTime == 'year' ">
WHERE a.year=b.year
</if>
) AS a
WHERE a.count_of_group
BETWEEN a.total_of_group / 2.0
AND a.total_of_group / 2.0 + 1
<if test="intervalTime == 'day' ">
GROUP BY a.year,a.month,a.day
</if>
<if test="intervalTime == 'month' ">
GROUP BY a.year,a.month
</if>
<if test="intervalTime == 'year' ">
GROUP BY a.year
</if>
参考技术C 也遇到这个问题貌似不支持,建议写个通用存储过程,直接用java代码拼好sql传进去执行

MyBatis--动态SQL(bind的用法)

  bind标签可以使用OGNL表达式创建一个变量并将其绑定到上下文中。

   在前面的UserMapper.xml有一个selectByUser方法,这个方法用到了like查询条件。

   使用concat函数连接字符串,在MySQL中,这个函数支持多个参数,但在Oracle中支持两个参数。由于不同数据库之间的语法差异,如果更换数据库,有些SQL语句可能就需要重写。针对这种情况,可以使用bind标签来避免由于更换数据库带来的一些麻烦 

 

   bind标签的两个属性都是必选项,name为绑定到上下文的变量名,value为OGNL表达式。创建一个bind标签的变量后,就可以在下面直接使用,使用bind拼接字符串不仅可以避免因更换数据库而修改SQL,也能防止SQL注入。

多数据库支持:

  bind标签并不能解决更换数据库带来的所有问题,那么还可以通过什么方式支持不同的数据库?这需要用到if标签以及由MyBatis提供的databaseIdProvider数据库厂商标识配置。

 

 

   这里的DB_VENDOR会通过DatabaseMetaData#getDatabaseProductName()返回的字符串进行设置。由于通常情况下这个字符串都非常长而且相同的产品的不同版本会返回不同的值,所以通常通过设置属性别名来使其变短,代码如下:

 

 

   上面列举了常见的数据库产品名称,在有property配置时,databaseId将被设置为第一个能匹配数据库产品名称的属性键对应的值,如果没有匹配的属性则会被设置为null。如果getDatabaseProductName()返回Microsoft SQL Server,databaseId将被设置为sqlserver。

 

 

 

   当基于不同数据库运行时,MyBatis会根据配置找到合适的SQL去执行。

  数据库的更换可能只会引起某个SQL语句的部分不同,可以使用if标签配合默认的上下文中的_databaseId参数这种写法去实现。这样可以避免大量重复的SQL出现,方便修改。

  首先需要在application.properties配置下数据库标识:(本人使用的是mysql,其它的替换就行)

 

  然后selectByUser方法可以修改如下:

 1     <select id="selectByUser" resultType="com.beilin.menber.entity.SysUser">
 2         select<include refid="userBase"/>
 3         from
 4         sys_user
 5         <where>
 6         <if test="userName != null and userName !=\'\'">
 7             <if test="_databaseId ==\'mysql\'">
 8             and user_name like concat(\'%\',#{userName},\'%\')
 9             </if>
10             <if test="_databaseId == \'oracle\'">
11             and user_name like \'%\'||#{userName}||\'%\'
12             </if>
13         </if>
14         <if test="userEmail != null and userEmail != \'\'">
15             and user_email like concat(\'%\',#{userEmail},\'%\')
16         </if>
17         </where>
18     </select>

 

MyBatis常用OGNL表达式

 

  1. e1 or e2
  2. e1 and e2
  3. e1 == e2,e1 eq e2
  4. e1 != e2,e1 neq e2
  5. e1 lt e2:小于
  6. e1 lte e2:小于等于,其他gt(大于),gte(大于等于)
  7. e1 in e2
  8. e1 not in e2
  9. e1 + e2,e1 * e2,e1/e2,e1 - e2,e1%e2
  10. !e,not e:非,求反
  11. e.method(args)调用对象方法
  12. e.property对象属性值
  13. e1[ e2 ]按索引取值,List,数组和Map
  14. @class@method(args)调用类的静态方法
  15. @class@field调用类的静态字段值

 

PS:因作者能力有限,如有误还请谅解

以上是关于mybatis中支持mysql中的变量吗?的主要内容,如果未能解决你的问题,请参考以下文章

mybatis的使用及详解

MyBatis源码分析-MyBatis初始化流程

mybatis支持oracle和mysql吗

MyBatis源码分析-SQL语句执行的完整流程

SpringBoot_Mybatis MyBatisPlus

Mybatis学习过程记录