之前的dao层接口总是做着重复性的工作,造成代码冗余,而且也不美观,其实mybatis框架可以帮我们做dao层接口中session的操作、关闭部分。
之前的dao层实现类:
public class StudentDaoImpl implements IStudentDao {
private SqlSession session;
@Override
public void insertStudent(Student student) {
try {
//1、获取sqlsession
session = MyBatisUtil.getSqlSession();
//2、操作
session.insert("insertStudent",student);
//3、提交
session.commit();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (session != null) {
//4、关闭
session.close();
}
}
}
}
现在我们不再使用dao层实现类,将其工作交互给框架完成。
测试类需要进行改动:
public class MyView {
private SqlSession session;
private IStudentDao dao;
//此方法一般用于搭建测试方法的执行环境
@Before
public void before() throws IOException {
session = MyBatisUtil.getSqlSession();
dao = session.getMapper(IStudentDao.class);
}
@Test
public void test01() {
Student student = new Student("张三", 23);
dao.insertStudent(student);
session.commit();
}
}
在使用@Before注解修饰的before方法中完成sqlsession对象的获取,并使用session.getMapper()获取到指定的dao层接口。
必须的要求:
- mapper的namespace值必须为对应接口的全限定性类名
- mapper的statement必须与对应接口的相应方法名相同
mapper.xml:
<?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.dao.IStudentDao">
<insert id="insertStudent" parameterType="Student">
insert into student(name,age) value (#{name}, #{age})
</insert>
</mapper>
IStudentDao接口:
public interface IStudentDao {
void insertStudent(Student student);//插入
}
框架底层会使用jdk的动态代理生成代理类Proxy完成之前dao层实现类的工作。
- 由于mapper.xml中的namespace修改为对应接口的全限定类名,所以,日志文件也需要进行改动,不然执行过程中不会出现日志信息。
log4j.properties日志文件:
##define an appender named console
log4j.appender.console=org.apache.log4j.ConsoleAppender
#The Target value is System.out or System.err
log4j.appender.console.Target=System.out
#set the layout type of the apperder
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#set the layout format pattern
#log level: fatal error warn info debug trace
log4j.appender.console.layout.ConversionPattern=[%-5p] %m%n
##define a logger
#fatal error warn info debug trace
#log4j.rootLogger=debug,console
log4j.logger.com.dao.IStudentDao=trace,console
log4j.logger后面跟mapper.xml的namespace值。
- 注意,一般情况下映射文件名会被命名为与之对应的接口的简单类名。这样就可以在主配置文件中以package标签的方式对映射文件进行注册了。这条要求,不是Mapper的动态代理所要求的。
mybatis.xml主配置文件:
<!-- 注册映射文件 -->
<mappers>
<!-- <mapper resource="com/dao/mapper.xml" /> -->
<package name="com.dao"/>
</mappers>
在注册映射文件时,不再指定某一个单独的映射文件,而是使用package直接加载映射文件所在的包。
此时映射文件的命名就必须与接口名字一致。
这么做的原因:
在实际开发中可能会存在多个dao层接口,每一接口都有一 一对应的映射文件,那么在注册这么多的映射文件时,就很麻烦,所以就直接注册映射文件所在的包,让映射文件名与接口名一致,同样可以在主配置文件中完成注册。
映射文件与接口名相同这条要求并不是mapper动态代理所必须要求的。
这只是为了操作更加方便。
完成mapper动态代理的条件只有两项:
- mapper的namespace值必须为对应接口的全限定性类名
- mapper的statement必须与对应接口的相应方法名相同
此时的项目结构:
之前为了测试方便将service层去掉了。。
(所用到的jar包:
log4j-1.2.17.jar
lombok-1.16.18.jar
mybatis-3.4.5.jar
mysql-connector-java-5.1.7-bin.jar)