1.1 parameterType
parameterType: 接口中方法参数的类型, 类型的完全限定名或别名。这个属性是可选的,因为 MyBatis可以推断出具体传入语句的参数,默认值为未设置(unset)。接口中方法的参数从 java 代码传入到mapper 文件的 sql 语句。
int 或 java.lang.Integer
hashmap 或 java.util.HashMap
list 或 java.util.ArrayList
student 或 com.bjpowernode.domain.Student
<select>,<insert>,<update>,<delete>
都可以使用 parameterType 指定类型。
例如:
<delete id="deleteStudent" parameterType="int">delete from student where id=#{studentId}
</delete>
等同于
<delete id="deleteStudent" parameterType="java.lang.Integer">delete from student where id=#{studentId}
</delete>
1.2 MyBatis 传递参数
从 java 代码中把参数传递到 mapper.xml 文件。
1.3 一个简单参数
Dao 接口中方法的参数只有一个简单类型(java 基本类型和 String)
,占位符 #{ 任意字符 },和方法的参数名无关。
接口方法:
/*** 一个简单类型的参数:* 简单类型:mybatis把java的基本数据类型和String都叫简单类型。* 在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}* @param id* @return*/public Student selectStudentById(Integer id);
mapper 文件:
<select id="selectStudentById" resultType="com.zep.domain.Student" parameterType="java.lang.Integer">select id,name,email,age from student where id=#{studentId}
</select>
注意:
#{studentId} , 这里的studentId是自定义的变量名称,和方法参数名无关。
测试方法:
@Testpublic void testSelectStudentById() {/*** 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)* getMapper能够获取dao接口对应的实现类对象。*/SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class); // 这句代码可以自动创建dao接口的实现类对象//调用dao的方法,执行数据库的操作Student student = dao.selectStudentById(1001);System.out.println("学生=" + student);}
1.4 多个参数-使用@Param
当 Dao 接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名”),mapper 文件使用#{自定义参数名}。
例如定义 List selectStudent( @Param(“personName”) String name ) { … }
mapper 文件 select * from student where name = #{ personName}
接口方法:
/*** 多个参数:命名参数,在形参定义的前面加入@Param("自定义参数名称")*/public List<Student> selectMultiParam(@Param("myname") String name, @Param("myage") Integer age);
mapper 文件:
<!--多个参数,使用@Param命名--><select id="selectMultiParam" resultType="com.zep.domain.Student">select * from student where name=#{myname} or age=#{myage}</select>
测试方法:
@Testpublic void testSelectMultiParam() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectMultiParam("李四", 20);for (Student student : students) {System.out.println("学生=" + student);}sqlSession.close();}
1.5 多个参数-使用对象
使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。 每一个属性就是一个参数。
语法格式:
#{ property,javaType=java 中数据类型名,jdbcType=数据类型名称 }
javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。
常用格式 #{ property }
创建保存参数值的对象 QueryParam:
package com.zep.vo;public class QueryParam {private String paramName;private Integer paramAge;public String getParamName() {return paramName;}public void setParamName(String paramName) {this.paramName = paramName;}public Integer getParamAge() {return paramAge;}public void setParamAge(int paramAge) {this.paramAge = paramAge;}
}
接口方法:
/*** 多个参数,使用java对象作为接口中方法的参数**/List<Student> selectMultiObject(QueryParam param);
mapper 文件:
<!--多个参数。使用java对象的属性值,作为参数的实际值适用对象的语法:#{属性名,javaType=类型名称,jdbcType=数据类型} 很少用javaType:指java中的属性数据类型jdbcType: 在数据库中的数据类型例如:#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}select * from student where name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}我们使用的简化方式:#{对应接口的参数的类型,即参数对象的属性名},javaType,jdbcType的值mybatis反射能获取。不用提供--><select id="selectMultiObject" resultType="com.zep.domain.Student">select * from student where name=#{paramName}or age=#{paramAge}</select>
或者
<select id="selectMultiObject" resultType="com.zep.domain.Student">select * from student where name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}
</select>
测试方法:
@Testpublic void testSelectMultiObject() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);QueryParam queryParam = new QueryParam();queryParam.setParamName("张三");queryParam.setParamAge(28);List<Student> students = dao.selectMultiObject(queryParam);for (Student student : students) {System.out.println("学生=" + student);}sqlSession.close();}
1.6 多个参数-按位置
参数位置从 0 开始, 引用参数语法 #{ arg 位置 }
, 第一个参数是#{arg0}
, 第二个是#{arg1}
注意:mybatis-3.3 版本和之前的版本使用#{0},#{1}方式, 从 mybatis3.4 开始使用#{arg0}方式。
接口方法:
/*** 多个参数,简单类型的,按位置来传值* mybatis 3.4之前,使用#{0},#{1}* mybatis 3.4之后,使用#{arg0},#{arg1}*/List<Student> selectMultiPosition(String name,Integer age);
}
mapper 文件:
<!--多个参数使用位置--><select id="selectMultiPosition" resultType="com.zep.domain.Student">select * from student where name=#{arg0}or age=#{arg1}</select>
测试方法:
@Testpublic void testSelectMultiPosition() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectMultiPosition("李四",20);for (Student stu : students) {System.out.println("学生=" + stu);}}
1.7 多个参数-使用 Map
Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key,Object 类型的值存储参数。 mapper 文件使用# { key }
引用参数值。
例如:Map<String,Object> data = new HashMap<String,Object>();
data.put(“myname”,”李力”);
data.put(“myage”,20);
接口方法:
/*** 多个参数,使用Map存放多个值*/List<Student> selectMultiByMap(Map<String,Object> map);
mapper 文件:
<!--多个参数,使用Map,使用的语法:#{map的key}--><select id="selectMultiByMap" resultType="com.zep.domain.Student">select * from student where name=#{myname}or age=#{myage}</select>
@Testpublic void testSelectMultiByMap() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);Map<String,Object> data = new HashMap<>();data.put("myname","张三");data.put("myage",20);List<Student> students = dao.selectMultiByMap(data);for (Student stu : students) {System.out.println("学生=" + stu);}}
1.8 #和$
#:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替sql 语句的“?”。这样做更安全,更迅速,通常也是首选做法
mapper 文件
<select id="selectStudentById" resultType="com.zep.domain.Student">select id,name,email,age from student where id=#{studentId}
</select>
转为 MyBatis 的执行是:
String sql=” select id,name,email,age from student where id=?”;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1005);
解释:
where id=? 就是 where id=#{studentId}
ps.setInt(1,1005) , 1005 会替换掉 #{studentId}
$ 字符串替换,告诉 mybatis 使用$包含的“字符串”替换所在位置
。使用 Statement 把 sql 语句和${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。
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=1001String sql="select id,name, email,age from student where id=" + "1001";使用的Statement对象执行sql, 效率比PreparedStatement低。
$:可以替换表名或者列名, 你能确定数据是安全的。可以使用$
接口方法:
List<Student> selectUse$Order(@Param("colName") String colName);
mapper文件:
<!--$替换列名--><select id="selectUse$Order" resultType="com.zep.domain.Student">select * from student order by ${colName}</select>
测试文件:
@Testpublic void testSelectUse$Order() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectUse$Order("name");for (Student student : students) {System.out.println("学生=" + student);}sqlSession.close();}
1.8.1 # 和 $区别
1. #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高2. #能够避免sql注入,更安全。3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低4. $有sql注入的风险,缺乏安全性。5. $:可以替换表名或者列名
1.9 完整代码
StudentDao .java:
package com.zep.dao;import com.zep.domain.Student;
import com.zep.vo.QueryParam;
import org.apache.ibatis.annotations.Param;import java.util.List;
import java.util.Map;public interface StudentDao {/*** 一个简单类型的参数:* 简单类型:mybatis把java的基本数据类型和String都叫简单类型。* 在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}* @param id* @return*/public Student selectStudentById(Integer id);/*** 多个参数:命名参数,在形参定义的前面加入@Param("自定义参数名称")*/public List<Student> selectMultiParam(@Param("myname") String name, @Param("myage") Integer age);/*** 多个参数,使用java对象作为接口中方法的参数**/List<Student> selectMultiObject(QueryParam param);List<Student> selectMultiStudent(Student student);/*** 多个参数,简单类型的,按位置来传值* mybatis 3.4之前,使用#{0},#{1}* mybatis 3.4之后,使用#{arg0},#{arg1}*/List<Student> selectMultiPosition(String name,Integer age);/*** 多个参数,使用Map存放多个值*/List<Student> selectMultiByMap(Map<String,Object> map);/****/List<Student> selectUse$(@Param("myname") String name);List<Student> selectUse$Order(@Param("colName") String colName);}
mapper文件(StudentDao.xml):
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zep.dao.StudentDao"><!--parameterType:dao接口中方法参数的数据类型。parameterType它的值是java的数据类型全限定名称或者是mybatis定义的别名例如:parameterType="java.lang.Integer"parameterType="int"注意:parameterType不是强制的,mybatis通过反射机制能够发现接口参数的数据类型,所以可以没有。一般我们也不写。使用#{}之后,mybatis执行sql使用的是jdbc中的PreparedStatement对象由mybatis执行下面的代码:1. mybatis创建Connection,PreparedStatement对象String = "select id,name,email,age from student where id=?";PreparedStatement pst = conn.preparedStatement(sql);pst.setInt(1,1001);2.执行sql封装为resultType="com.zep.domain.Student"这个对象ResultSet rs = pst.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方法调用的返回值--><select id="selectStudentById" resultType="com.zep.domain.Student" parameterType="java.lang.Integer">select id,name,email,age from student where id=#{studentId}</select><!--多个参数,使用@Param命名--><select id="selectMultiParam" resultType="com.zep.domain.Student">select * from student where name=#{myname} or age=#{myage}</select><!--多个参数。使用java对象的属性值,作为参数的实际值适用对象的语法:#{属性名,javaType=类型名称,jdbcType=数据类型} 很少用javaType:指java中的属性数据类型jdbcType: 在数据库中的数据类型例如:#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}select * from student where name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}我们使用的简化方式:#{对应接口的参数的类型,即参数对象的属性名},javaType,jdbcType的值mybatis反射能获取。不用提供--><select id="selectMultiObject" resultType="com.zep.domain.Student">select * from student where name=#{paramName}or age=#{paramAge}</select><select id="selectMultiStudent" resultType="com.zep.domain.Student">select * from student where name=#{name}or age=#{age}</select><!--多个参数使用位置--><select id="selectMultiPosition" resultType="com.zep.domain.Student">select * from student where name=#{arg0}or age=#{arg1}</select><!--多个参数,使用Map,使用的语法:#{map的key}--><select id="selectMultiByMap" resultType="com.zep.domain.Student">select * from student where name=#{myname}or age=#{myage}</select><!--使用 ${} --><select id="selectUse$" resultType="com.zep.domain.Student">select * from student where name=${myname}</select><!--$替换列名--><select id="selectUse$Order" resultType="com.zep.domain.Student">select * from student order by ${colName}</select>
</mapper>
测试代码:
package com.zep;import com.zep.dao.StudentDao;
import com.zep.domain.Student;
import com.zep.utils.MybatisUtils;
import com.zep.vo.QueryParam;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class TestMybatis {@Testpublic void testSelectStudentById() {/*** 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)* getMapper能够获取dao接口对应的实现类对象。*/SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class); // 这句代码可以自动创建dao接口的实现类对象//调用dao的方法,执行数据库的操作Student student = dao.selectStudentById(1001);System.out.println("学生=" + student);}@Testpublic void testSelectMultiParam() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectMultiParam("李四", 20);for (Student student : students) {System.out.println("学生=" + student);}sqlSession.close();}@Testpublic void testSelectMultiObject() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);QueryParam queryParam = new QueryParam();queryParam.setParamName("张三");queryParam.setParamAge(28);List<Student> students = dao.selectMultiObject(queryParam);for (Student student : students) {System.out.println("学生=" + student);}sqlSession.close();}@Testpublic void testSelectMultiStudent(){SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);Student student = new Student();student.setAge(20);student.setName("张三");List<Student> students = dao.selectMultiStudent(student);for (Student stu : students) {System.out.println("学生=" + stu);}}@Testpublic void testSelectMultiPosition() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectMultiPosition("李四",20);for (Student stu : students) {System.out.println("学生=" + stu);}}@Testpublic void testSelectMultiByMap() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);Map<String,Object> data = new HashMap<>();data.put("myname","张三");data.put("myage",20);List<Student> students = dao.selectMultiByMap(data);for (Student stu : students) {System.out.println("学生=" + stu);}}@Testpublic void testSelectUse$() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectUse$("'李四'");for (Student student : students) {System.out.println("学生=" + student);}sqlSession.close();}@Testpublic void testSelectUse$Order() {SqlSession sqlSession = MybatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectUse$Order("email");for (Student student : students) {System.out.println("学生=" + student);}sqlSession.close();}}