# MyBatis的SQL语句中#和$取值的含义和区别
使用步骤:
1:Mapper接口中传入的变量参数(JavaBean对象/Map/简单数据类型(Long/Double等))
<pre><code>
/**
* 从数据库中查询一条数据
* @param id
* @return
*/
People selectAPeople(Long id);
</code></pre>
2:在Mapper.xml文件中编写SQL使用#/$取变量[中]我们需要的内容
<pre><code>
<select id="selectAPeople" resultMap="peopleMapPackLeaderList">
SELECT id,name FROM people
WHERE id=#{id}
</select>
</code></pre>
## #和$符号的含义
>#{id}:取Map内key为'id'所对应的value,取JavaBean对象的'id'属性,取简单数据类型参数'id'(Integer/Long)的值
>${id}:取配置文件中的属性名为'id'的值,取JavaBean对象的'id'属性
### #符号
1.取Map内key所对应的value
<pre><code>
//HashMap实参:
User user = mapper.getAUserByName(new HashMap<String, String>() {
private static final long serialVersionUID = -158122886455409850L;
{
put("username", "张三");
put("password", "zhangsan");
}
});
//mapper接口传参:
/**
* 通过账号密码,查询一条数据
* @param username
* @param password
* @return
*/
public User getAUserByName(HashMap<String, String> user);
//SQL:
<select id="getAUserByName" resultType="user">
SELECT id,username,password
FROM user
WHERE username=#{username} AND password=#{password}
</select>
</code></pre>
2.取JavaBean对象的属性
如果给SQL传入的参数是JavaBean对象,那么#{name}会取出这个对象内的名字为name的属性
<pre><code>
//mapper接口传参:
/**
* 保存一条people数据
* @param people
*/
void saveAPeople(People people);
//SQL:
<insert id="saveAPeople" useGeneratedKeys="true" keyProperty="id">
INSERT INTO people(name)
VALUES(#{name})
</insert>
</code></pre>
3.取简单数据本身的值
如果给SQL传入的参数是简单的数据对象例如Integer/Long/Double/String等等,那么#{name}在取对象的name属性失败后,会直接把参数对象取出来
<pre><code>
//mapper接口传参:
/**
* 从数据库中查询一条数据
* @param id
* @return
*/
People selectAPeople(Long id);
//SQL:
<select id="selectAPeople" resultMap="peopleMapPackLeaderList">
SELECT id,name FROM people
WHERE id=#{id}
</select>
</code></pre>
### $符号
>${id}:取配置文件中的属性名为'id'的值,取JavaBean对象的'id'属性
1.取配置文件中的属性
${}会首先在mybatis-config.xml主配置文件中查找是否有同名的属性
下面的SQL会查找到配置文件中‘username’属性,而不是传入的People对象的username属性
<pre><code>
//mapper接口传参:
/**
* 从数据库中查询一条数据
* @param people
* @return
*/
People selectAPeople(People people);
//SQL:
<select id="selectAPeople" resultMap="peopleMapPackLeaderList">
SELECT id,name FROM people
WHERE name=${username}
//最终的取出结果是配置文件中数据库用户名root
</select>
</code></pre>
2.取JavaBean对象的属性
与#{}类似,不过不同的是取值是直接拼装到SQL中,左右没有‘’单引号,下面会说区别
<pre><code>
//mapper接口传参:
/**
* 查询排序好的User数据
* @return
*/
List<User> getUserListOrdered(@Param("columnName")String columnName);
//SQL:
<select id="getUserListOrdered" resultType="user">
SELECT id,username,password
FROM user
ORDER BY ${columnName} DESC
</select>
</code></pre>
### #和$符号两者的区别
1.组成SQL语句不同:
#{}相当于PreparedStatement,组成的SQL变量部分由占位符?占位,运行时候把取到的值拼装到一个单引号里面,转化成SQL
> SELECT * FROM user WHERE name=#{name}
>运行时变成:
>SELECT * FROM user WHERE name='张三'
${}相当于Statement,没有占位(会有SQL注入问题),运行时候把取到的值直接拼装SQL中
> SELECT * FROM user WHERE name=${name}
>运行时变成:
>SELECT * FROM user WHERE name=张三 //报错!
2.取值范围不同:
如上面两者的取值功能介绍,#{}可以取Map内的value,JavaBean对象的属性,直接取简单数据(Integer/Long)的值
但是${}基本上只能取JavaBean对象的属性,取配置文件的属性我从来没用过(感觉没有用,还经常会出错)
3.#{}有单引号!${}则冇
上面两条不同中#{}完胜,但是${}组成的SQL语句没有单引号是自己独特的优势:
在组成SQL的时候,如果不是拼装条件而是拼装SQL语句本体(不用单引号的column名)时候用
比如说:ORDER BY ${columnName},用#{}会报错,因为把列名加了单引号
### $符号要注意的地方
这里自己发现一个例外,${}并不是完全不能取简单对象的值
>例外:如果foreach的item是简单的数据类型(Integer/Double等),可以直接取出来
<pre><code>
//mapper接口传参:
/**
* forEach语句的练习
* @param idList
* @return
*/
List<Employee> getEmployeeListUseForEach(Long[] idList);
//SQL:
<select id="getEmployeeListUseForEach" resultType="employee">
SELECT * FROM employee
where id in
<foreach collection="array" open="(" close=")" item="id" separator="," index="i">
${id}
</foreach>
</select>
//Preparing: SELECT * FROM employee where id in ( 2 , 3 )
</code></pre>
over
by wangyk
网友评论