mybatis使用${}时,必须要用@Param

今天在做项目时,有好几个需求都是对成绩进行分段,这些需求只是——表名,id字段名,分数字段名不一样,其他都一样。于是就考虑能不能把表名,id字段名,分数名换成变量,这样就一劳永逸了。而且如果其他伙伴有同样的需求,也可以直接调我的方法。

一.做之前

原本想用mybatis plus做,但是mp太麻烦了。最终还是考虑用mybatis

二.正片

第一次尝试:

1
2
@Select("select count(*) as segCount from #{tbName} where #{idTbName}=#{idValue} and ( #{scoreTbName} between #{val1} and #{val2} ) ")
Integer getSeg(@Param("tbName") String tbName, String idTbName, Long idValue, String scoreTbName, Integer val1, Integer val2);

报错:

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@d5b549d] was not registered for synchronization because synchronization is not active
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@d5b549d]

错因:

#占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替sql 语句的“?”。这样做更安全,更迅速,通常也是首选做法。

$ 字符串替换,告诉 mybatis 使用$包含的“字符串”替换所在位置。使用 Statement 把 sql 语句和${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。

#{}

#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
如:WHERE SID = #{sid},如果传入的值是s01,那么解析成SQL时的值为WHERE SID = "s01"。
#可以防止防止sql注入。

${}

$将传入的数据直接显示生成在sql中。
如:ORDER BY ${sage},如果传入的值是age,那么解析成SQL时的值为ORDER BY age。
$方式一般用于传入数据库对象,例如传入表名,字段名。

第二次尝试:

1
2
@Select("select count(*)  from ${tbName} where ${idTbName}=#{idValue} and ( ${scoreTbName} between #{val1} and #{val2} ) ")
Integer getSeg(@Param("tbName") String tbName, String idTbName, Long idValue, String scoreTbName, Integer val1, Integer val2);

把表名,字段名由#{}换成${}

报错:

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@d5b549d] was not registered for synchronization because synchronization is not active
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@d5b549d]

错因:

@Param注解的作用是声明参数时,如果使用 #{} 或 ${} 的方式都可以。
不使用@Param注解来声明参数时,必须使用使用 #{}方式,如果使用${} 的方式,会报错。