MyBatis代理模式开发
前面已经使用MyBatis完成了对Emp表的CRUD操作,都是由SqlSession调用自身方法发送SQL命令并得到结果的,实现了MyBatis的入门。但是却存在如下缺点:
- 不管是selectList()、selectOne()、selectMap(),都是通过SQLSession对象的API完成增删改查,都只能提供一个查询参数。如果要多个参数,需要封装到JavaBean或者Map中,比较麻烦。
- 返回值类型较固定。
- 只提供了映射文件,没有提供数据库操作的接口,不利于后期的维护扩展。
在MyBatis中提供了另外一种成为Mapper代理(或称为接口绑定)的操作方式。在实际开发中也使用该方式。下面我们就是要Mapper代理的方式来实现对Emp表的CRUD操作吧,还有完成多个参数传递、模糊查询、自增主键回填等更多的技能实现。 优点如下:
- 接口 模块之间有规范了
- 参数的处理多样了,接口中的方法参数列表由我们自己决定
- 通过代理模式由mybatis提供接口的实现类对象 我们不用写实现类了
一、使用Mapper代理方式实现查询
1.1.准备接口文件
在mapper包下创建接口 EmpMapper,代码如下:
public interface EmpMapper { /*查询所有员工接口 * 返回所有员工封装在一起的Emp List集合*/ List<Emp> findAllEmp(); }
1.2.准备映射文件
这里的映射文件必须和EmpMapper在同一个目录中,否则会出错误内容如下:
<?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"> <!-- namespace需要指定接口文件的路径 --> <mapper namespace="com.augus.mapper.EmpMapper"> <!-- 1 接口的名字和Mapper映射为文件名字必须保持一致(不包含拓展名) 2 Mapper映射文件的namespace必须是接口的全路径名 3 sql语句的id必须是对应方法的名 4 EmpMapper映射文件应该和接口编译之后放在同一个目录下 List<Emp> findAllEmp(); --> <select id="findAllEmp" resultType="com.augus.pojo.Emp"> select * from emp </select> </mapper>
1.3.在sqlMapConfig.xml核心配置文件中添加映射文件
注意这里配置的时候要使用之前讲过的方式一:通过mapper映射文件的文件路径导入 使用的mapper标签的resource属性
<mappers>
<!--mapper映射文件的文件路径导入-->
<mapper resource="com\augus\mapper\EmpMapper.xml"/>
<mapper resource="com\augus\mapper\DeptMapper.xml"/>
</mappers>
截图如下:

1.4.创建测试代码
创建测试代码,测试结果如下:
public class Test02 { private SqlSession sqlSession; @BeforeEach public void setUp(){ SqlSessionFactoryBuilder ssfb =new SqlSessionFactoryBuilder(); InputStream resourceAsStream = null; try { resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); } catch (IOException e) { e.printStackTrace(); } SqlSessionFactory factory=ssfb.build(resourceAsStream) ; sqlSession=factory.openSession(); } //查询所有员工 @Test public void testFindAllDept(){ /*获取字节码文件*/ EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); //执行SQL List<Emp> allEmp = mapper.findAllEmp(); for (Emp emp : allEmp) { System.out.println(emp); } } @AfterEach public void tearDown(){ //关闭 sqlSession.close(); } }
二、Mapper代理模式浅析
回顾上面测试代码写法:
public static void main(String[] args) { //前三步都相同 InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = factory.openSession(); //这里不再调用SqlSession的api,而是获得了接口对象,调用接口中的方法。 UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> list = mapper.getUserByName("tom"); }
通常的EmpMapper接口都没有实现的方法却可以使用,是为什么呢?
原因是使用了—动态代理,MyBatis初始化时对接口的处理:MapperRegistry是Configuration中的一个属性, 它内部维护一个HashMap用于存放mapper接口的工厂类,每个接口对应一个工厂类。mappers中可以 配置接口的包路径,或者某个具体的接口类。
<mappers>
<!--mapper映射文件的文件路径导入-->
<mapper resource="com\augus\mapper\EmpMapper.xml"/>
<mapper resource="com\augus\mapper\DeptMapper.xml"/>
</mappers>
当解析mappers标签时,会判断解析到的是mapper配置文件时,会再将对应配置文件中的增删改查 标签 封装成MappedStatement对象,存入mappedStatements中。当判断解析到接口时,会 建此接口对应的MapperProxyFactory对象,存入HashMap中,key=接口的字节码对象,value =此接口对应的MapperProxyFactory对象。

浙公网安备 33010602011771号