3.1 Dao 代理实现数据库操作
3.1.1 步骤
(1) 去掉 Dao 接口实现类
(2) getMapper 获取代理对象
只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对 象。该方法的参数为指定 Dao 接口类的 class 值。
package com.hrf; import com.hrf.Utils.MybatisUtils; import com.hrf.dao.StudentDao; import com.hrf.domain.Student; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; public class MybatisTest { @Test public void testSelectById(){ //获取SqlSession SqlSession session = MybatisUtils.getSqlSession(); //获取dao的代理 StudentDao dao = session.getMapper(StudentDao.class); Student student = dao.SelectStudentById(1001); System.out.println("学生信息"+student); session.close(); } } . `
使用工具类:
StudentDao studentDao = MyBatisUtil.getSqlSession().getMapper(StudentDao.class);
getMapper()创建的对象,是代替我们自己创建的 StudentDaoImpl 类
3.2 深入理解参数
从 java 代码中把参数传递到 mapper.xml 文件。
3.2.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
更多看资源中的有关别名的文件或者 mybatis-3.5.1.pdf 的 15 页。
<select>,<insert>,<update><delete>都可以使用parameterType指定类型
例如:
<select id="SelectStudentById" parameterType="java.lang.Integer" resultType="com.hrf.domain.Student"> select id,name,email,age from student where id=#{StudenId} </select>
3.2.2 [掌握]一个简单参数
Dao 接口中方法的参数只有一个简单类型(java 基本类型和 String),占 位符 #{ 任意字符 },和方法的参数名无关。
定义接口方法
Student selectById(int id);
配置文件写sql语句
<select id="selectById" resultType="com.hrf.domain.Student"> select * from student where id = #{StudentId} </select>
编写测试类
@Test public void selectId(){ SqlSession session = MybatisUtils.getSqlSession(); StudentDao studentDao = session.getMapper(StudentDao.class); Student student = studentDao.selectById(1005); System.out.println("学生信息"+student); session.close(); }
测试结果:
3.2.3 [掌握]多个参数-使用@Param
当 Dao 接口方法多个参数,需要通过名称使用参数。 在方法形参前面加 入@Param(“自定义参数名”),mapper 文件使用#{自定义参数名}。
例如定义:LIst<Student> selectStudent(@Param("psersonName") String name){....}
mapper文件
select * from student where name = #{personName}
示例:
创建接口方法
List<Student> selectSomeStudent(@Param("studentName") String name, @Param("StudentAge") int age);
mapper配置文件sql语句
<select id="selectSomeStudent" resultType="com.hrf.domain.Student"> select * from student where name = #{studentName} or age = #{StudentAge} </select>
测试类:
@Test public void selectSomeStudent(){ SqlSession session = MybatisUtils.getSqlSession(); StudentDao dao = session.getMapper(StudentDao.class); List<Student> students = dao.selectSomeStudent("王五", 20); for (Student stu : students){ System.out.println("查到的学生信息"+stu); session.close(); } }
测试结果:
3.2.4 [掌握]多个参数-使用对象
使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。 每一个 属性就是一个参数。
语法格式:#{property.javaType = java中数据类型名,jdbcType=数据类型名称}
javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。常用格 式 #{ property }
(mybatis-3.5.1.pdf 第 43 页 4.1.5.4 小节:)
创建一个实体类对象
package com.hrf.domain; public class QueryParam { private String queryName; private int queryAge; public String getQueryName() { return queryName; } public void setQueryName(String queryName) { this.queryName = queryName; } public int getQueryAge() { return queryAge; } public void setQueryAge(int queryAge) { this.queryAge = queryAge; } }
创建接口方法:
List<Student> selectMultiObject(QueryParam queryParam);
mapper文件sql语句:
<select id="selectMultiObject" resultType="com.hrf.domain.Student"> select * from student where name=#{queryName} or id = #{queryAge} </select>
编写测试类
@Test public void selectMultiObject(){ SqlSession session = MybatisUtils.getSqlSession(); StudentDao dao = session.getMapper(StudentDao.class); QueryParam queryParam = new QueryParam(); queryParam.setQueryName("王五"); queryParam.setQueryAge(26); List<Student> students = dao.selectMultiObject(queryParam); for (Student stu : students){ System.out.println("学生信息"+stu); session.close(); } }
测试结果:
3.2.5 [了解]多个参数-按位置
参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是#{arg0},第二个是#{arg1
(注意:mybatis-3.3 版本和之前的版本使用#{0},#{1}方式, 从 mybatis3.4 开 始使用#{arg0}方式。)
接口方法:
List selectByNameAndAge(String name,int age);
mapper 文件:
<select id="selectByNameAndAge" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where name=#{arg0} or age =#{arg1} </select>
测试方法:
@Test public void testSelectByNameAndAge(){ //按位置参数 List<Student> stuList = studentDao.selectByNameAndAge("李力",20); stuList.forEach( stu -> System.out.println(stu)); }
3.2.6 [了解]多个参数-使用 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);
接口方法:List selectMultiMap(Map<string,object> map);
mapper 文件:
<select id="selectMultiMap" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where name=#{myname} or age =#{myage} </select>
测试方法:
@Test public void testSelectMultiMap(){ Map<String,Object> data = new HashMap<>(); data.put("myname","李力");// #{myname} data.put("myage",20); // #{myage} List<Student> stuList = studentDao.selectMultiMap(data); stuList.forEach( stu -> System.out.println(stu)); }
3.2.7 [掌握] #和$
#:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替 sql 语句的“?”。这样做更 安全,更迅速,通常也是首选做法,
mapper 文件
<select id="selectById" resultType="com.bjpowernode.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 语句和${}的内容连接起来。主要用在替换表名,列名,不同 列排序等操作。
#{}的特点:
1)使用的PrepareStatement对象,执行sql语句,效率高
2)使用的PrepareStatement对象,能避免sql语句,sql语句执行更安全
3)#{}常常作为列值使用,位于等号右边,#{}位置的值和数据类型有关的
${}的特点:
1)使用Statement对象,执行sql语句,效率低
2)${}占位符的值,使用的字符串链接方式,有sql注入的风险,有代码安全的问题
3)${}数据是原样使用的,不会区分数据类型
4)${}常用做表名或者列名,在能保证数据安全的情况下使用${}
示例:
创建接口方法:
List<Student> queryStudent(@Param("studentId") String name);
在mapper文件中写sql语句:
<select id="queryStudent" resultType="com.hrf.domain.Student"> select * from student order by ${studentId} desc </select>
编写测试类方法
@Test public void queryStudent(){ SqlSession session = MybatisUtils.getSqlSession(); StudentDao dao = session.getMapper(StudentDao.class); List<Student> students = dao.queryStudent("id"); for (Student stu : students){ System.out.println("stu==>"+stu); session.close(); } }
测试结果: