4.4 #{}占位符

在上面的增删改查操作中,SQL语句中的值是写死在SQL中,而在实际开发中,此处的值往往是用户提交过来的值,因此这里我们需要将SQL中写死的值替换为占位符。
使用占位符完成上面的增删改查练习

练习5、查询:查询指定id的员工信息

mapper文件配置:
<!-- 练习5: 查询emp表中指定id的员工信息 -->
<select id="findById" resultType="com.tedu.pojo.Emp">
	select * from emp where id=#{id}
</select>
java代码示例:
/** 练习5: 查询emp表中指定id的员工信息 */
@Test
public void testFindById() {
	//执行sql语句, 返回执行结果
	Emp emp = session.selectOne(
			"EmpMapper.findById", 1 );
	System.out.println( emp );
}

练习6:往emp表中添加一个新员工

mapper文件配置:
<!-- 练习6: 新增员工信息: 张飞 Java开发工程师 15000 如果通过map集合传输参数, 需要保证占位符中的变量名 和map集合中的key保持一致 如果通过pojo对象传输参数, 需要保证占位符中的变量名 和对象中的属性名保持一致, 或者在pojo中有对应的 getXxx方法 -->
<update id="insert2">
	insert into emp values
	(null, #{name}, #{job}, #{salary})
</update>
java代码示例:
/** 练习6: 新增员工信息: 张飞 Java开发工程师 15000 */
@Test
public void testInsert2() {
	//将要传输的参数封装到map集合中
	//Map map = new HashMap();
	//map.put("name", "张飞");
	//map.put("job", "Java开发工程师");
	//map.put("salary", 15000);
	
	//也可以将要传输的参数封装到Emp对象中
	Emp emp = new Emp();
	emp.setName("关羽123");
	emp.setJob("保安");
	emp.setSalary(8000.0);
	//执行sql语句
	int rows = session.update("EmpMapper.insert2", emp);
	//提交事务
	session.commit();
	System.out.println( "影响的行数: "+rows );
}

练习7:修改员工信息: 张飞 架构师 25000

mapper文件配置:
<!-- 练习7: 修改员工信息: 张飞 架构师 25000 -->
<update id="update2">
	update emp set job=#{job}, salary=#{salary} 
	where name=#{name}
</update>
java代码示例:
/** 练习7: 修改员工信息: 张飞 架构师 25000 */
@Test
public void testUpdate2() { 
	//将参数封装到Emp对象中
	Emp emp = new Emp();
	emp.setName("张飞");
	emp.setJob("架构师");
	emp.setSalary(25000.0);
	//执行sql语句
	int rows = session.update("EmpMapper.update2", emp);
	//提交事务
	session.commit();
	System.out.println("影响的行数: "+rows);
}

练习8:删除指定id的员工信息

mapper文件配置:
<!-- 练习8:删除emp表中指定id的员工信息 -->
<insert id="delete2" parameterType="String">
	delete from emp where id=#{id}
</insert>
java代码示例:
/* * 练习8:删除emp表中指定id的员工信息 */
public void testDelete2() throws IOException{
	......
	//执行SQL语句
	int rows = session.delete("EmpMapper.delete2", 1);
	//提交事务
	session.commit();
	System.out.println("影响行数:"+rows);
}

4.5#{}和${}占位符

在上面的增删改查练习中,当SQL语句中包含的参数值是传递过来的,在SQL语句中我们会通过 #{} 占位符进行占位,在SQL语句真正执行时,再将传递过来的值替换SQL语句中的占位符。
其实,#{} 就是JDBC中的问号(?)占位符,因此为了安全考虑,在执行时会对传递过来的值进行转译处理。
例如:查询指定name的员工信息,SQL语句为:

select * from emp where name=#{name}

其实就等价于JDBC中: select * from emp where name=?,如果传过来的参数值为:王海涛,那么最终执行的SQL语句为:

select * from emp where name='王海涛'

那么如果我们在传递的时候不是一个参数值,而是一个SQL片段呢?
例如在查询时,我们想动态的传递查询的列:

select 查询的列?? from emp

此时传递过来的应该是一个SQL片段,不同于上面的参数值,如果此时还用 #{},也会像上面一样被转译处理,这不是我们希望看到的。
如果不想让传过来的SQL片段被转译处理,而是拼接在SQL语句中,那么这里可以使用 ${},例如:

select ${columns} from emp

示例1:查询emp表中所有员工的名称(name)、职位(job):

mapper文件配置:
<!-- 练习9: 动态显示要查询的列 -->
<select id="findAll2" resultType="com.tedu.pojo.Emp">
	select  ${cols}  from emp
</select>
java代码示例:
/** 练习9: 动态显示要查询的列 * select * from emp * select id, name from emp * select id, salary from emp * select name, job from emp */
@Test
public void testFindAll2() {
	Map map = new HashMap();	
	//map.put("cols", "id, name");
	//map.put("cols", "id, name, salary");
	map.put("cols", "id,name,job,salary");
	//执行sql语句, 返回结果
	List<Emp> list = session.selectList(
					"EmpMapper.findAll2", map);
	//输出结果
	for ( Emp e : list ) {
		System.out.println( e );
	}
}

示例2: 根据name模糊查询emp表

mapper文件配置:
<!-- 练习10: 根据name模糊查询emp表 -->
<select id="findAll3" resultType="com.tedu.pojo.Emp">
	select  *  from  emp
	where  name  like  '%${name}%'
</select>
<!-- 练习11: 根据name模糊查询emp表 -->
<select id="findAll4" resultType="com.tedu.pojo.Emp">
	select  *  from  emp
	where  name  like  #{name}
</select>
java代码示例:
/** * 练习10: 根据name模糊查询emp表 * '%王%' '%刘%' */
@Test
public void testFindAll3() {
	//将参数封装到map集合中
	Map map = new HashMap();
	map.put("name", "涛");
	//执行sql, 返回结果
	List<Emp> list = session.selectList(
				"EmpMapper.findAll3", map);
	//输出结果
	for (Emp emp : list) {
		System.out.println( emp );
	}
}
/** * 练习11: 根据name模糊查询emp表 * '%王%' '%刘%' */
@Test
public void testFindAll4() {
	//将参数封装到map集合中
	Map map = new HashMap();
	map.put("name", "%刘%");
	//执行sql, 返回结果
	List<Emp> list = session.selectList(
			"EmpMapper.findAll4", map);
	//输出结果
	for (Emp emp : list) {
		System.out.println( emp );
	}
}

<mark>需要注意的是,在传递 KaTeX parse error: Expected 'EOF', got '#' at position 39: … 总结:在大多数情况下还是使用#̲{}占位符,而{}多用于为不带引号的字符串进行占位!</mark>


备注

指定变量

	<!-- 练习3:修改员工信息,将刘德华的 job改为 演员 salary 改为88888 -->
	<update id="update">
		update emp set job='演员' ,  salary=88888 where name='刘德华'
	</update>
	
	<!-- 练习4 -->
	<delete id="delete">
		delete from emp where name='刘德华'
	</delete>
	
	<!-- ================== day 34 =================== -->
	<!-- 练习:新增员工信息:张飞 Java开发工程师 15000 -->
	<insert id="insert2">
		insert into emp values( null , #{name} , #{job} , #{salary} ) 
	</insert>
	
	
	<!-- 练习:修改员工信息:张飞 架构师 25000 -->
	<update id="update2">
		update emp set job=#{job} , salary=#{salary} where name=#{name} 
	</update>
/** * 练习5:查询name 为 刘德华 的员工信息 */
	@Test
	public void testFindById() {
		
		String name = "刘德华";
		List<Empolyee> list = session.selectList("EmpMapper.findByName", name) ; 
		for (Empolyee e : list) {
			System.out.println(e);
		}
	}
	/** * 练习4:删除name为 刘德华 的记录 */
	@Test
	public void testDelete() {
		int rows = session.update("EmpMapper.delete");
		session.commit();
		System.out.println("影响行数:"+rows);
	}
	
	
	/** * Employee 封装 值 * 练习:新增员工信息:张飞 Java开发工程师 15000 */
	@Test
	public void testInsert2() {
		Object parameter = new Empolyee(null , "张飞" , "Java开发工程师" , 15000.0);
		int rows  = session.insert("EmpMapper.insert2", parameter ) ; 
		session.commit() ;
		System.out.println("影响行数:"+rows);
	}
	
	/** * Map 封装 值 * 练习:修改员工信息:张飞 架构师 25000 */
	@Test
	public void testUpdate2() {
		//将要传递的参数封装到 map 集合中 
		Map<String , String> parameter = new HashMap<>() ; 
		parameter.put("name", "张飞");
		parameter.put("job" , "架构师")  ; 
		parameter.put("salary", "25000") ;
		
		int rows = session.insert("EmpMapper.update2" , parameter ) ; 
		
		session.commit() ;
		System.out.println("影响行数:"+rows);
		
		
	}