版本
SpringBoot调用MyBatis访问数据库,依赖为org.mybatis.spring.boot
,版本为2.1.2
。
两种调用方式
两种调用方式为:注解方式和SqlProvider方式。
两种方式所遵循的规则相同:
无论是否使用
@Param
,都可以支持多参数,令传入与引用的参数名相同即可。
因此建议:不使用@Param
直接传参,且保持传入与引用的参数名一致。
注解方式
@Select({"select id, name, age, class from student"})
List<Student> getStudents();
SqlProvider方式
Mapper文件:
@SelectProvider(type = StudentSqlProvider.class, method = "getStudents")
List<Student> getStudents();
SqlProvider文件:
public String getStudents() {
String sql = "select id, name, age, class from student";
return sql;
}
注解方式传参
注解方式传参建议采用以下规则:
无论是否使用
@Param
,都可以支持多参数,令传入与引用的参数名相同即可。
1个参数
@Select({"select id, name, age, class from student where id = #{id}"})
Student getStudent(Integer id);
@Select({"select id, name, age, class from student where id = #{id}"})
Student getStudent(@Param("id") Integer id);
@Select({"select id, name, age, class from student where id = #{id}"})
Student getStudent(@Param("id") Integer studentId);
@Select({"select id, name, age, class from student where id = #{id}"})
Student getStudent(Integer aValue);
如上4种方式,效果相同。MyBatis都可顺利识别id参数值。
特别注意第4种方式,在不加@Param
的情况下,即使传入的参数名与引用的参数名不匹配,却依然可以正确识别。但若加了@Param
,指定的参数名与引用的参数名就必须相同:
@Select({"select id, name, age, class from student where id = #{id}"})
Student getStudent(@Param("aValue") Integer id);
如上,运行会报错。
2个参数
@Select({"select id, name, age from student where age = #{age} and class = #{class}"})
Student getStudent(Integer age, Integer class);
@Select({"select id, name, age from student where age = #{age} and class = #{class}"})
Student getStudent(@Param("age") Integer age, @Param("class") Integer class);
@Select({"select id, name, age from student where age = #{age} and class = #{class}"})
Student getStudent(@Param("age") Integer studentAge, @Param("class") Integer studentClass);
@Select({"select id, name, age from student where age = #{age} and class = #{class}"})
Student getStudent(@Param("age") Integer studentAge, Integer class);
如上4种方式,效果相同。MyBatis都可顺利识别age和class参数值。
注意第4种方式,允许部分字段使用@Param
来指定参数名,其他字段依然使用传入的名称。
与1个参数不同的是,多参数情况下:
- 若不使用
@Param
,传入与引用的参数名必须匹配。 - 若使用
@Param
,@Param
指定的参数名与引用的参数名必须匹配。
若不匹配则运行报错。
更换参数顺序
@Select({"select id, name, age from student where age = #{age} and class = #{class}"})
Student getStudent(Integer class, Integer age);
@Select({"select id, name, age from student where age = #{age} and class = #{class}"})
Student getStudent(@Param("class") Integer class, @Param("age") Integer age);
@Select({"select id, name, age from student where age = #{age} and class = #{class}"})
Student getStudent(@Param("class") Integer studentClass, @Param("age") Integer studentAge);
如上。sql语句没有变化,依然是age先判断,class后判断。但传入的参数顺序变了,第1个参数是class,第2个参数是age。但MyBatis顺利识别出了参数值。
SqlProvider方式传参
SqlProvider方式传参建议采用与注解方式传参相同的规则:
无论是否使用
@Param
,都可以支持多参数,令传入与引用的参数名相同即可。
唯一的区别是,SqlProvider方式传参可以使用Map
接收:
// Mapper传入参数
@SelectProvider(type = StudentSqlProvider.class, method = "getStudent")
Student getStudent(Integer class, Integer age);
// 对应参数接收
public String getStudent(Integer age, Integer class) {
String sql = "select id, name, age, class from student where 1=1";
sql += " and class = " + class;
sql += " and age = " + age;
return sql;
}
// Map接收
public String getStudent(Map<String, Integer> map) {
String sql = "select id, name, age, class from student where 1=1";
sql += " and class = " + map.get("class");
sql += " and age = " + map.get("age");
return sql;
}
如上,两种接收方式都可顺利接收到class
和age
2个参数。
- 非Map接收,只需要参数名相同,不需要参数顺序相同。
- Map接收,从Map中获取参数时要与传入参数的名称相同。
org.apache.ibatis.binding.BindingException
使用如上规则,同样的代码,有的正常运行,有的会报:
org.apache.ibatis.binding.BindingException
经验证,与IDEA有关,暂不能确定是版本问题还是环境导致。出问题的IDEA是2018版本,更换为2020版本问题解决。