目录

1. 区别

2. 使用注意

2.1 #{}中变量名写法的注意

2.2 ${}中变量名写法的注意

2.3 使用${}而不适用#{}的场景:字符串替换

3. 使用实例

3.1 #{}占位符

3.2 ${}占位符


1. 区别

#{}: 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,一个 #{ } 被解析为一个参数占位符 。

${}: 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换。

例子:

eg 1: select id,name,age from student where name=#{name} ; 解析为:select id,name,age from student where name='cy';

eg 2: select id,name,age from student where name=${name}; 解析为:select id,name,age from student where name=cy;

使用#{}可以有效的防止 SQL 注入,提高系统安全性。

 在大多数情况下还是经常使用#,但在不同情况下必须使用$.

2. 使用注意

2.1 #{}中变量名写法的注意

  • #{}占位符可以用来设置参数,如果传进来的是基本类型,也就是(string,long,double,int,boolean,float等),那么#{}里面的变量名可以随意写,什么abc,xxx等等,这个名字和传进来的参数名可以不一致。
  • 如果传进来的是pojo类型,那么#{}中的变量名必须是pojo的属性名,可以写成属性名,也可以写属性名.属性名

参数是int,不需要设置parameterType

<delete id="deleteStudentById" >
    delete from student where id=#{XXXdoukeyi}
</delete>

parameterTypepojo类,如果使用pojo类型作为参数,那么必须提供get方法,也就是框架在运行的时候需要通过反射根据#{}中的名字,拿到这个值放到sql语句中,如果占位符中的名称和属性不一致,那么报ReflectionException

<insert id="insertStudent" parameterType="Student">
    insert into student(name,age,score) values(#{name},#{age},#{score})
</insert>

 

注意:不能这样写:

<insert id="insertStudent" parameterType="Student">
    insert into student(name,age,score) values(#{Student.name},#{Student.age},#{Student.score})
</insert>

否则会报一个错误(会将Student当成一个属性),所以我们类名就直接省略不写就可以了:

### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'Student' in 'class bean.Student'

2.2 ${}中变量名写法的注意

  • 如果传进来的是基本类型,也就是(string,long,double,int,boolean,float等),那么#{}里面的变量名必须写value
<delete id="deleteStudentById" >
    delete from student where id=${value}
</delete>
  • 如果传进来的是pojo类型,那么#{}中的变量名必须是pojo的属性名,可以写成属性名,也可以写属性名.属性名但是由于是拼接的方式,对于字符串我们需要自己加引号。
<insert id="insertStudent" parameterType="Student">
    insert into student(name,age,score) values('${name}',${age},${score})
</insert>

与上面一样,不能将类名写进来:

<!--这是错误的-->
<insert id="insertStudent" parameterType="Student">
    insert into student(name,age,score) values('${Student.name}',${Student.age},${Student.score})
</insert>

2.3 使用${}而不适用#{}的场景:字符串替换

默认情况下,使用 #{} 参数语法时,MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中直接插入一个不转义的字符串。 比如 ORDER BY 子句(Mybatis中Order By 不能使用#号.md_zhouwenjun0820的博客-,这时候你可以:

ORDER BY ${columnName}

这样,MyBatis 就不会修改或转义该字符串了。

当 SQL 语句中的元数据(如表名或列名)是动态生成的时候,字符串替换将会非常有用。 举个例子,如果你想 select 一个表任意一列的数据时,不需要这样写:

@Select("select * from user where id = #{id}")
User findById(@Param("id") long id);

@Select("select * from user where name = #{name}")
User findByName(@Param("name") String name);

@Select("select * from user where email = #{email}")
User findByEmail(@Param("email") String email);

// 其它的 "findByXxx" 方法

而是可以只写这样一个方法:

@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);

其中 ${column} 会被直接替换,而 #{value} 会使用 ? 预处理。 这样,就能完成同样的任务:

User userOfId1 = userMapper.findByColumn("id", 1L);
User userOfNameKid = userMapper.findByColumn("name", "kid");
User userOfEmail = userMapper.findByColumn("email", "noone@nowhere.com");

 

3. 使用实例

3.1 #{}占位符

#{}占位符用来设置参数,参数的类型可以有3种:基本类型,自定义类型,Map。

基本类型:

基本类型,参数名称与占位符中的名称无关。

#{} 传入值时,sql解析时,参数是带引号的

如果用了@Param("xxx") ,则mybatis会自动生成map作为入参,那么参数名称则必须与占位符一致

<select id="findById" parameterType="int" resultType="cn.wh.vo.Role">
           select * from t_role where id = #{xxxid}
       </select>

测试:

@Test
       public void testSelectOne(){
           Role role = (Role)session.selectOne("cn.wh.mapper.RoleMapper.findById",1);
           System.out.println(role.getName());
       }

自定义类型

自定义类型作为参数,自定义类中需要为为属性提供get方法,如果没有提供get方法,那么会根据占位符中的名称去反射获取值,如果占位符中的名称和属性不一致,那么报ReflectionException。

<select id="findListBypage" parameterType="cn.wh.util.PageUtil" resultType="Role">
           select * from t_role limit #{index},#{size}
       </select>

测试:

@Test
    public void testPage1(){
           PageUtil pu = new PageUtil();
           pu.setIndex(3);
           pu.setSize(3);
           List<Role> list = session.selectList("cn.wh.mapper.RoleMapper.findListBypage", pu);
           for(Role r:list){
               System.out.println(r.getName());
           }
       }

Map

Map作为参数类型,key和占位符中的名称一致即可,如果名称不一致那么将会把null,传递到占位符中。

 

3.2 ${}占位符

<!-- 查询所有 -->
<select id="findAll" parameterType="map" resultType="cn.wh.vo.Role">
        select * from ${tableName}
 </select>

测试:

@Test
       public void testSelectList(){
           Map<String,String> map = new HashMap<String,String>();
           map.put("tableName", "t_role");
           List<Role> list = session.selectList("cn.wh.mapper.RoleMapper.findAll",map);
           for(Role role:list){
               System.out.println(role.getId()+"----"+role.getName());
           }
       }

作为连接符使用:

<select id="selectLike1" parameterType="map" resultType="Role">
           select *from t_role where name like '${name}%';
    </select>

测试:

@Test
   public void testLike2(){
       Map<String,String> map = new HashMap<String,String>();
       map.put("name", "黄");
       List<Role> list = session.selectList("cn.wh.mapper.RoleMapper.selectLike1",map);
           for(Role r:list){
               System.out.println(r.getName());
           }
       }