MyBatis配置文件相关
占位符
MyBatis中有两种占位符:#{}和${}。
- #{}解析传递进来的参数数据
- ${}对传递进来的参数原样拼接在SQL中
#{}占位符
主要用来设置参数
,可以是基本数据类型,也可以是java bean。
如果传递的是基本数据类型
,并且只有一个
参数,那么#{}中的变量名可以任意命名,但是在多个参数时变量名必须与传入的一致才能正确获取,所以建议统一按照传入的参数名来获取
。
User getUser(String name,int age);
<select id="getUser" resultType="com.demo.bean.User">
select * from user where name=#{name} and age=#{age};
</select>
如果传递的是pojo类型作为参数,那么此pojo类中必须提供get方法。#{}中的参数应该写的是属性名,如果有多个pojo类型,并且其中具有相同的属性名则写参数名点属性名。
public class Teacher {
String tname;
int tno;
//省略get/set
}
public interface TeacherMapper{
@Select("select * from teacher where tno=#{tno}")
Teacher getTeacherByAnnoction(Teacher teacher);
}
//测试类
public class DemoTest{
@Autowired
TeacherMapper mapper;
@Test
public void test(){
Teacher teacher = new Teacher();
teacher.setTno(2);
mapper.getTeacherByAnnoction(teacher);
}
}
如果有多个pojo类作为参数,那么需要使用 参数名点属性名方式获取:
//多个student类
public class Student {
int tno;
//省略get/set
}
public interface TeacherMapper{
@Select("select * from teacher where tno=#{teacher.tno}")
Teacher getTeacherByAnnoction(Teacher teacher,Student student);
}
//测试类
public class DemoTest{
@Autowired
TeacherMapper mapper;
@Test
public void test(){
Teacher teacher = new Teacher();
teacher.setTno(2);
Student student = new Student();
student.setTno(1);
mapper.getTeacherByAnnoction(teacher,student);
}
}
当然,上面多参数的例子仅仅只是举例,并不推荐这样使用,如果有多种复杂参数的需求的话推荐使用Map进行传递。
public interface TeacherMapper{
@Select("select * from teacher where tno=#{teacher.tno}")
Teacher getTeacherByAnnoction(Map map);
}
//测试类
public class SpringbootApplicationTests {
@Autowired
TeacherMapper mapper;
@Test
public void contextLoads() {
Teacher teacher = new Teacher();
teacher.setTno(2);
HashMap map = new HashMap();
map.put("teacher", teacher);
mapper.getTeacherByAnnoction(map);
}
}
从例子中可以看出#{param}中的参数时HashMap中的key,如果是基本数据类型则直接取值,如果是pojo类则点属性就可以取得。
注意:
动态表名,动态列名,动态排序不能使用#{}。它只能作为参数数据传递。以下例子中都是错误的写法:
select * from #{table};
select #{column} from table;
select * from table order by #{column}
select * from table where #{column}=#{param}
原因在于使用#{}相当于JDBC中的PreparedStatement预编译,编译后的参数使用占位符代替,而我们传入的参数只能作为参数执行了,表名列名在编译时已经固定。
${}拼接符
${}拼接符中传入的内容会被直接拼接在SQL语句中。
因此它可以用来动态得设置表名,列名,排序列名,或者动态地拼接SQL语句,但是它有SQL注入的风险!
@Select(select * from teacher ${
value})
Teacher getTeacher(String sql);
@Test
public void test(){
mapper.getTeacher("where id=1");
}
上述例子中,传入的参数会直接与SQL语句拼成select * from teacher where id=1;
如果有多个参数,要求 $ {}中的参数名必须与传入的一致,或者使用Map传入,${}中的参数名必须与map中的Key一致。
public interface TeacherMapper{
@Select(select ${
param1} from ${
param2})
List<Teacher> getTeacher(String param1,String param2);
@Select(select ${
param1} from ${
param2})
List<Teacher> getTeacherByMap(Map map);
}
@Test
public void test(){
//方式1
mapper.getTeacher("*","teacher");
//方式2
HashMap map = new HashMap();
map.put("param1","*");
map.put("param2","teacher");
mapper.getTeacherByMap(map);
}
如果传入的是pojo类,用法和#{}相同,不做详细介绍。
#{}和${}的区别
- 主要区别在于功能上,一个传递参数一个拼接SQL。#{}是有预编译的更加安全,SQL语句较为固定的情况下效率更高。
- 能使用#{}尽量不用${}因为它有SQL注入风险。需要拼接SQL语句可以在MyBatis的xml文件中设置动态SQL。
转义字符的处理
在MyBatis的配置文件中使用的是xml格式,如果需要用到大于小于会和标签的尖括号冲突。还有一些其他的转义字符。通常有三种处理方式:
- 使用${}拼接:(不推荐)
<select id="getTeacher" resultType="com.springboot.bean.Teacher">
select * from teacher where tno ${value} 2 limit 0,1;
</select>
public interface TeacherMapper {
Teacher getTeacherById(String value);
}
@Test
public void contextLoads() {
mapper