MyBatis传递参数
从 java 代码中把参数传递到 mapper.xml 文件。
1、parameterType
parameterType : dao接口中方法参数的数据类型。
parameterType它的值是java的数据类型全限定名称或者是mybatis定义的别名
< select >,< insert >,< update >,< delete >都可以使用 parameterType 指定类型。
官方文档别名
例如:parameterType=“java.lang.Integer”
parameterType=“int”
注意: parameterType不是强制的,mybatis通过反射机制能够发现接口参数的数类型。可以没有。 一般不写。
使用#{}之后, mybatis执行sql是使用的jdbc中的PreparedStatement对象
由mybatis执行下面的代码:
- mybatis创建Connection , PreparedStatement对象
String sql="select id,name, email,age from student where id=?";
PreparedStatement pst = conn.preparedStatement(sql);
pst.setInt(1,1001);
- 执行sql封装为resultType="com.b0kuwa.entity.Student"这个对象
ResultSet rs = ps.executeQuery();
Student student = null;
while(rs.next()){
//从数据库取表的一行数据, 存到一个java对象属性中
student = new Student();
student.setId(rs.getInt("id));
student.setName(rs.getString("name"));
student.setEmail(rs.getString("email"));
student.setAge(rs.getInt("age"));
}
return student; //给了dao方法调用的返回值
2、传递一个简单类型的参数
简单类型: mybatis把java的基本数据类型和String都叫简单类型。
在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}
接口:public Student selectStudentById(Integer id)
mapper:select id,name, email,age from student where id=#{studentId}
#{studentId} , studentId 是自定义的变量名称,和方法参数名无关。
StudentDao.java
Student selectStudentById(Integer id);
StudentDao.xml
<select id="selectStudentById" resultType="com.b0kuwa.entity.Student">
select * from student where id = #{studentId}
</select>
测试
@Test
public void selectStudentById() {
Student student = MybatisUtils.getSqlSession().getMapper(StudentDao.class).selectStudentById(1001);
System.out.println(student);
}
3、传递多个参数
3.1 使用@Param【常用】
当 Dao 接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名”),
mapper 文件使用#{自定义参数名}。
接口:
List<Student> selectMultiParam(@Param("myname") String name,@Param("myage") Integer age);
Mapper:
<select id="selectMultiParam" resultType="com.b0kuwa.entity.Student">
select * from student where name = #{myname} or age = #{myage}
</select>
Test:
@Test
public void selectMultiParam() {
List<Student> students = MybatisUtils.getSqlSession().getMapper(StudentDao.class).selectMultiParam("张三", 18);
students.forEach(student -> System.out.println(student));
}
3.2 使用对象传值【常用】
多个参数, 使用java对象的属性值,作为参数实际值
使用对象语法: #{属性名,javaType=类型名称,jdbcType=数据类型} 很少用。
javaType:指java中的属性数据类型。
jdbcType:在数据库中的数据类型。
例如: #{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
简化方式: #{属性名} ,javaType, jdbcType的值mybatis反射能获取,不用提供
<!--完整-->
<select id="selectMultiObject" resultType="com.b0kuwa.entity.Student">
select id,name, email,age from student where
name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}
</select>
<!--简化-->
<select id="selectMultiObject" resultType="com.b0kuwa.entity.Student">
select * from student where name = #{paramName} or age = #{paramAge}
</select>
public class QueryParam {
private String paramName;
private Integer paramAge;
//创建get和set
接口:
List<Student> selectMultiObject(QueryParam queryParam);
测试:
@Test
public void selectMultiObject() {
QueryParam queryParam = new QueryParam();
queryParam.setParamName("张三");
queryParam.setParamAge(18);
List<Student> students = MybatisUtils.getSqlSession().getMapper(StudentDao.class).selectMultiObject(queryParam);
students.forEach(student -> System.out.println(student));
}
也可以直接使用Student类传递参数
接口:
List<Student> selectMultiStudent(Student student);
Mapper:
<select id="selectMultiStudent" resultType="com.b0kuwa.entity.Student">
select * from student where name = #{name} or age = #{age}
</select>
测试:
@Test
public void selectMultiStudent() {
Student student = new Student();
student.setName("楚子航");
student.setAge(19);
List<Student> students = MybatisUtils.getSqlSession().getMapper(StudentDao.class).selectMultiStudent(student);
students.forEach(stu -> System.out.println(stu));
}
3.3 按位置传值,多个参数-简单类型
mybatis 3.4之前,使用 #{0} ,#{1}
mybatis 3.4之后 ,使用 #{arg0} ,#{arg1}
接口:
List<Student> selectMultiPosition( String name,Integer age);
Mapper:
<select id="selectMultiPosition" resultType="com.b0kuwa.entity.Student">
select * from student where name = #{arg0} or age = #{arg1}
</select>
测试:
@Test
public void selectMultiPosition() {
List<Student> students = MybatisUtils.getSqlSession()
.getMapper(StudentDao.class)
.selectMultiPosition("张三",20);
students.forEach(stu -> System.out.println(stu));
}
3.4 使用Map传值
语法:#{map中的key}
接口:
List<Student> selectMultiByMap(Map<String,Object> map);
Mapper:
<select id="selectMultiByMap" resultType="com.b0kuwa.entity.Student">
select * from student where name = #{key1} or age=#{key2}
</select>
测试:
@Test
public void selectMultiByMap() {
Map<String, Object> map = new HashMap<>();
map.put("key1","张三");
map.put("key2",18);
List<Student> students = MybatisUtils.getSqlSession()
.getMapper(StudentDao.class)
.selectMultiByMap(map);
students.forEach(stu -> System.out.println(stu));
}
3.5 #和$
3.5.1 $取值
接口:
List<Student> selectUse$(@Param("myname") String name);
Mapper:
<select id="selectUse$" resultType="com.b0kuwa.entity.Student">
select * from student where name = ${myname}
</select>
测试:
@Test
public void selectUse$() {
List<Student> students = MybatisUtils.getSqlSession()
.getMapper(StudentDao.class)
.selectUse$("张三");
students.forEach(student -> System.out.println(student));
}
通过报错可以发现,$使用的是字符串拼接的方式,使用的是Statement
3.5.2 $替换列名
接口:
List<Student> selectUse$Order(@Param("colName") String colName);
Mapper:
<select id="selectUse$Order" resultType="com.b0kuwa.entity.Student">
select * from student order by ${colName}
</select>
测试:
@Test
public void selectUse$Order() {
List<Student> students = MybatisUtils.getSqlSession()
.getMapper(StudentDao.class)
.selectUse$Order("age");
students.forEach(student -> System.out.println(student));
}
3.5.3 #与$区别
select id,name, email,age from student where id=#{studentId}
#的结果: select id,name, email,age from student where id=?
select id,name, email,age from student where id=${studentId}
$的结果:select id,name, email,age from student where id=1001
String sql=“select id,name, email,age from student where id=” + “1001”;
使用的Statement对象执行sql, 效率比PreparedStatement低。
$可以替换表名或者列名, 能确定数据是安全的.
- #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
- #能够避免sql注入,更安全。
- $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
- $有sql注入的风险,缺乏安全性。
- $:可以替换表名或者列名