MyBatis--5.MyBatis的动态代理

403 阅读3分钟

1.引言

​ 原先我们使用的mapper.xml的时候都是通过调用StudentDaoImpl中实现的方法,而它的调用规则是通过insert方法定位到mapper.xml中的<insert/>标签,然后再通过statement获取到对应的SQL语句;

insertStudent()为例:该方法的调用方式就是通过sqlSession的insert()方法定位到mapper中的insert标签,然后通过statement的参数“insertStudent”方法定位到对应的SQL语句;

	@Override
	public void insertStudent(Student student) {
		sqlSession = SqlSessionUtil.getSqlSession();
        //先通过insert方法定位到mapper中的insert标签,然后通过insertStudent定位到SQL语句
		sqlSession.insert("insertStudent", student);
		SqlSessionUtil.closeSqlSession(sqlSession);
	}

​ 然而,如果我们的SQL的statement是惟一的话,也就是我们的<insert id="insertStudent" ></insert>的id是唯一的话,我们就可以直接获取到对应的SQL语句,而无需通过StudentDaoImpl来获取;

​ 但是这样也有一个问题,那就是我们的项目中可能存在多个mapper文件,而这些mapper文件中可能存在相同的<insert id="insertStudent" ></insert>,这时就不知道调用的是哪一个SQL语句了,所以我们这里还对mapper的namespace进行设定,将namespace属性修改为对应StudentDao的全限定类名<mapper namespace="com.mybatis.dao.StudentDao"></mapper>,这样我们在获取mapper时就有一个唯一标识,而该mapper中也有一个唯一的<insert id="insertStudent" ></insert>,这样就能解决问题了;

总结一下,如果想要使用MyBatis的动态代理,就要保证所有的statement(即所有SQL标签的id)是惟一的,这里的有两个限定,第一是将我们mapper.xmlnamespace设置为StudentDao 的全称限定类名;第二是将我们的SQL语句的<insert id="insertStudent">中的id设置成我们Student的方法名,这样就能保证我们获取的SQL语句唯一的;

这样在调用SQL语句的时候就可以直接通过statement也就是<insert id="insertStudent">中的id获取到对应的SQL语句;

=======================================================================================

2.修改项目代码:

​ 首先修改mapper.xmlnamespace,并且将所有的SQL标签的id改为StudentDao中对应的方法名

<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace为StudentDao的全限定类名-->
<mapper namespace="com.mybatis.dao.StudentDao">
	<insert id="insertStudent" parameterType="com.mybatis.beans.Student">
		INSERT INTO student(name,age,score) VALUES(#{name},#{age},#{score})
	</insert>
	<insert id="insertStudentCacheId">
		INSERT INTO student(name,age,score) VALUES(#{name},#{age},#{score})
		<selectKey resultType="int" keyProperty="id"  order="AFTER">
			select @@Identity
		</selectKey>
	</insert>
	<delete id="delectStudentById" parameterType="int">
		DELETE FROM student WHERE id = #{id}
	</delete>
	<update id="updateStudent">
		UPDATE student SET name=#{name},age=#{age},score=#{score} WHERE id = #{id}
	</update>
	<select id="selectAllStudent" resultType="com.mybatis.beans.Student">
		select id,name,age,score from student
	</select>
	<select id="selectStudentById" resultType="com.mybatis.beans.Student">
		select id,name,age,score from student where id=#{id}
	</select>
	<select id="selectStudentByName" resultType="com.mybatis.beans.Student">
		select id,name,age,score from student where name like '%' #{name} '%'
	</select>
</mapper>

​ 然后删除StudentDaoImpl类,在TestStudentDao类中添加以下的代码:

	private StudentDao dao = null;
	private SqlSession sql;
	//Before注解的作用是在每个测试方法执行之前执行该注解方法体中的内容
	//方法体中的代码就是获取对应的mapper,这样dao在调用的时候就会去mapper中寻找对应的SQL语句
	@Before
	public void before() {
		sql = SqlSessionUtil.getSqlSession();
		dao = sql.getMapper(StudentDao.class);
	}
	//After注解的作用是在每个测试方法执行之后执行该注解方法体中的内容
	//方法体中的代码是将sql关闭
	@After
	public void after() {
		sql.close();
	}

​ 修改所有执行增删改的对应测试代码:添加sql.commit()代码,让对应的操作写入数据库;

	@Test
	public void testInsertStudentCacheId() {
		Student student = new Student("张三", 23, 93.5);
		System.out.println("插入之前的student: " + student);
		dao.insertStudenCacheId(student);
		System.out.println("插入之后的student: " + student);
        //添加sql的提交,让数据库将对应操作写入
		sql.commit();
	}