MyBatis之Mapper动态代理开发

1.SqlSession的使用范围

1.SqlSessionFactoryBuilder
SqlSessionFactoryBuilder是以工具类的方式来使用:需要创建sqlSessionFactory时就new一个 SqlSessionFactoryBuilder

2.sqlSessionFactory
正常开发时,以单例方式管理sqlSessionFactory,整个系统运行过程中sqlSessionFactory只有一个实例,将来和Spring整合后由Spring以单例方式管理sqlSessionFactory

3.SqlSession
SqlSession是一个面向用户(程序员)的接口,程序员调用 SqlSession接口的方法进行操作数据库。那么我们会思考:SqlSession能否以单例方式使用???由于 SqlSession是线程不安全的,所以 SqlSession最佳应用范围在方法体内。也就是说在方法体内定义局部变量 SqlSession的对象来使用。

2.MyBatis开发DAO的方式

我们先来看看MyBatis原始开发dao的开发方式,发现原始开发的问题,然后再来看看MyBatis使用mapper动态代理开发dao的方式(也是MyBatis目前使用的开发dao的方式)。

2.1原始dao的开发方式

程序员需要编写dao接口:和dao接口的实现类:

然后就能在测试类中使用。测试类代码如下:

我们来看看这种方式开发有什么问题?

  • 1.dao的实现类中存在重复代码,整个mybatis操作的过程代码模板重复(都是先创建sqlSession、调用sqlSession的方法、关闭sqlSession)。
  • 2.dao的实现类中存在硬编码,调用sqlSession方法时将statement的id硬编码。

下面我们看看mapper动态代理的方式。

2.2mapper动态代理的方式

这种方式下程序员只需要写dao接口,dao接口实现对象由mybatis自动生成代理对象。因为本身dao在三层架构中就是一个通用的接口。

2.2.1mapper开发规范

要想让mybatis自动创建dao接口实现类的代理对象,必须要遵循一些规则:

  • 1.mapper.xml中 namespace指定为mapper接口的全限定名。此步骤的目的:将mapper.xml和mapper.java关联。
  • 2.mapper.xml中statement的id就是mapper.java中的方法名。
  • 3.mapper.xml中statement的parameterType和mapper.java中方法输入参数一致。
  • 4.mapper.xml中statement的resultType和mapper.java中方法的返回值类型一致。

采用这种方式后,我们便可将第一篇文章中提到的User.xml改为UserMapper.xml。文件目录如下:其中有些类我们会在后面用到。

2.2.2mapper.xml(映射文件)

mapper映射文件的命名方式建议表名加Mapper.xml,namespace指定为mapper接口的全限定名。

2.2.3mapper.java接口

mybatis提出了mapper接口,相当于dao接口,mapper接口的命名方式建议为表名加Mapper.

1
public interface UserMapper{};

2.3.4将mapper.xml在SqlMapConfing.xml中进行注册

<mappers>
 <mapper resource="mapper/UserMapper.xml"/>
</mappers>

2.3.5mapper接口返回单个对象和集合对象

在UserMapper.java中添加如下两个方法:

对于UserMapper.xml,不管查询记录是单条还是多条,在statement(即UserMapper.xml)中的resultType都定义一致,都是单条记录映射的pojo类型。

而对于UserMapper.java接口方法中的返回值,如果返回的是单个对象,返回值类型是pojo,生成的代理对象内部会自动通过selectOne获取记录,如果返回值类型是多条对象,生成的代理对象内部会自动通过selectList获取记录。

测试代码如下:

使用Mapper代理方式进行开发,使程序员只需要关注UserMapper.java接口中的方法,它的实现类由Mapper自动为我们生成,带来了很大的方便。但这种方式也有它的弊端。

2.3.6mapper代理开发的问题

  • 1.返回值的问题:如果方法(即UserMapper.java接口中的方法)调用的statement中返回是多条记录,而mapper.java方法的返回值为pojo,此时代理对象通过selectOne调用,但由于返回的是多条记录所以会报错:Expected one result (for null ) to be returned by selectOne() but found 4;
  • 2.输入参数的问题:使用mapper代理的方式开发,mapper接口方法的输入参数只有一个,可扩展性是否很差?答:可扩展性没有问题,因为dao层就是通用的,可以通过扩展pojo(定义pojo包装类型,后面第四篇文章–MyBatis输入输出映射会讲扩展pojo的知识)来将不同的参数(可以是pojo也可以是简单类型)传入进去。

2018.3.19更

欢迎加入我的Java交流1群:659957958。

2018.4.21更:如果群1已满或者无法加入,请加Java学习交流2群:305335626

3.联系

If you have some questions after you see this article,you can tell your doubts in the comments area or you can find some info by clicking these links.

记得扫一扫领一下红包再走哦