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.xml的namespace设置为StudentDao 的全称限定类名;第二是将我们的SQL语句的<insert id="insertStudent">中的id设置成我们Student的方法名,这样就能保证我们获取的SQL语句唯一的;
这样在调用SQL语句的时候就可以直接通过statement也就是<insert id="insertStudent">中的id获取到对应的SQL语句;
=======================================================================================
2.修改项目代码:
首先修改mapper.xml的namespace,并且将所有的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();
}