MyBatis框架的Dao代理
文章目录
Dao接口动态代理实现CRUD
动态代理: 使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象
1. 去掉Dao接口实现类
2. 使用getMapper()方法获取代理对象
只需调用 SqlSession 的 getMapper() 方法,即可获取指定接口的实现类对象。该方法的参数为指定 Dao 接口类的 class 值。
没有工具类的情况:
SqlSession session = factory.openSession();
StudentDao dao = session.getMapper(StudentDao.class);
//通过dao对象就可以调用StudentDao接口中声明的方法
使用工具类的情况:
StudentDao studentDao = MyBatisUtils.getSqlSession().getMapper(StudentDao.class);
3. 在sql映射文件中编写好CRUD的sql语句
默认Dao接口中已经声明好相对应的方法
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kaho.dao.StudentDao">
<select id="selectStudents" resultType="com.kaho.domain.Student">
select id,name,email,age from student order by id
</select>
<insert id="insertStudent">
insert into student values(#{id},#{name},#{email},#{age})
</insert>
<update id="updateStudent">
update student set age = #{age} where id=#{id}
</update>
<delete id="deleteStudent">
delete from student where id=#{studentId}
</delete>
</mapper>
4. 使用Dao代理对象方法执行sql语句
//查询
@Test
public void testSelectStudent(){
/**
* 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口的类)
* getMapper 能获取dao接口对应的实现类对象
*/
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
//传回的studentDao的类型是com.sun.proxy.$Proxy2 可知这是一个代理类的对象
//调用studentDao的方法,执行数据库的操作
List<Student> students = studentDao.selectStudents();
for (Student stu : students){
System.out.println("学生" + stu);
}
sqlSession.close();
}
//插入
@Test
public void testInsert() throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setId(1006);
student.setName("桐谷和人");
student.setEmail("heren@163.com");
student.setAge(18);
int nums = studentDao.insertStudent(student);
sqlSession.commit();//提交事务
sqlSession.close();
System.out.println("使用 Dao 添加数据:"+nums);
}
//更新
@Test
public void testUpdate() throws IOException {
StudentDao studentDao = MyBatisUtils.getSqlSession().getMapper(StudentDao.class);
Student student = new Student();
student.setId(1006);
student.setAge(28);
int nums = studentDao.updateStudent(student);
System.out.println("使用 Dao 修改数据:"+nums);
}
//删除
@Test
public void testDelete() throws IOException {
StudentDao studentDao = MyBatisUtils.getSqlSession().getMapper(StudentDao.class);
int nums = studentDao.deleteStudent(1006);
System.out.println("使用 Dao 修改数据:"+nums);
}
注意:
dao接口中不要使用重载方法,即不要使用同名、不同参数的方法
参数详解
传入参数: 从java代码中把数据传入到mapper文件的sql语句中。
1)parameterType
parameterType 是写在mapper文件中的 一个属性。 表示dao接口中方法的参数的数据类型。
接口方法:
public Student selectStudentById(Integer id)
mapper文件:
<select id="selectStudentById" parameterType="java.lang.Integer"
resultType="com.kaho.domain.Student">
select id,name,email,age from student where id=#{id}
</select>
parameterType的值是java的数据类型全限定名称或者是mybatis定义的别名
例如:parameterType="java.lang.Integer"
parameterType="int"
hashmap 或 java.util.HashMap
list 或 java.util.ArrayList
student 或 com.kaho.domain.Student
这个属性是可选的,因为 MyBatis 可以通过反射机制推断出具体传入语句的参数,默认值为未设置(unset)
2) 一个简单类型的参数
简单类型: mybatis把java的基本数据类型和String都叫简单类型。
在mapper文件获取简单类型的一个参数的值,使用 #{任意字符},与方法的参数名无关
接口方法:
public Student selectStudentById(Integer id)
mapper:
<select id="selectStudentById" parameterType="java.lang.Integer"
resultType="com.kaho.domain.Student">
select id,name,email,age from student where id=#{StudentId}
</select>
#{studentId} 中studentId 是自定义的变量名称,和方法参数名无关。
测试方法:
@Test
public void testSelectById(){
//一个参数
Student student = studentDao.selectById(1005);
System.out.println("查询 id 是 1005 的学生:"+student);
}
3) 多个参数 - 使用@Param命名参数
当 Dao 接口方法多个参数,需要通过名称使用参数。在方法形参前面加入**@Param(“自定义参数名”), mapper 文件使用#{自定义参数名}**。
接口方法:
public List<Student> selectMulitParam(@Param("myname") String name, @Param("myage") Integer age)
mapper文件:
<select id="selectMultiParam" resultType="com.kaho.domain.Student">
select * from student where name=#{myname} or age=#{myage}
</select>
测试方法:
@Test
public void testSelectMultiParam(){
List<Student> stuList = studentDao.selectMultiParam("桐谷和人",18);
stuList.forEach( stu -> System.out.println(stu));
}
4) 多个参数 - 使用java对象
多个参数,使用java对象的属性值作为参数实际值
使用对象语法: #{属性名,javaType=类型名称,jdbcType=数据类型}
javaType : 指java中的属性数据类型
jdbcType : 在数据库中的数据类型
例如: #{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。常用格式 #{ 属性名 }
在 com.kaho.vo 包下创建保存参数值的java对象的类 QueryParam :
package com.kaho.vo;
public class QueryParam {
private String paramName;
private int paramAge;
//get、set方法
}
接口方法:
List<Student> selectMultiObject(QueryParam param);
mapper文件 :
<!--简约形式-->
<select id="selectMultiObject" resultType="com.kaho.domain.Student">
select id,name,email,age from student where name=#{paramName} or age=#{paramAge}
</select>
<!--标准形式-->
<select id="selectMultiObject" resultType="com.kaho.domain.Student">
select id,name,email,age from student where name=# {paramName,javaType=string,jdbcType=VARCHAR} or age =# {paramAge,javaType=int,jdbcType=INTEGER}
</select>
测试方法 :
@Test
public void testSelectMultiObject(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
QueryParam param = new QueryParam();
param.setParamName("张三");
param.setParamAge(28);
List<Student> students = dao.selectMultiObject(param);
students.forEach(System.out::println);
}
关于包名的说明:
vo: value object , 放一些存储数据的类。比如说 提交请求参数, name ,age
现在想把name ,age 传给一个service 类。vo: view object , 从servlet把数据返回给浏览器使用的类,表示显示结果的类。
pojo: 普通的有set, get方法的java类。 普通的java对象
Servlet --- StudentService( addStudent( MyParam param) )
entity(domain域): 实体类, 和数据库中的表对应的类
5) 多个参数 - 按位置
参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是#{arg0}, 第二个是#{arg1}
接口方法:
List<Student> selectByNameAndAge(String name,int age);
mapper文件:
<select id="selectByNameAndAge" resultType="com.kaho.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));
}
6) 多个参数 - 使用 Map
Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key, Object 类型的值存储参数。 mapper 文件使用 # { key } 引用参数值。
接口方法:
List<Student> selectMultiMap(Map<String,Object> map);
先写测试方法:
@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));
}
mapper文件:
<select id="selectMultiMap" resultType="com.kaho.domain.Student">
select id,name,email,age from student where name=#{myname} or age =#{myage}
</select>