mybatis入门-mapper代理原理
原始dao层开发
在我们用mybatis开发了第一个小程序后,相信大家对于dao层的开发其实已经有了一个大概的思路了。其他的配置不用变,将原来的test方法,该为dao的方法,将原来的返回值,直接在dao层进行一下接收就可以了。依然是老一套,先是大框架,然后写配置文件及UserMapper.xml文件这一系列的操作。如果不明白的,请参考本人博客《入门第一个程序》。
我们需要做的就是,首先建立一个会话工厂(SqlSessionFactory),然后用会话工厂创建会话(SqlSession)。然后通过读取配置文件得到sql语句,执行,然后返回数据给dao层的对象。具体操作如下
首先,在原来的基础上创建一个dao层的接口。
然后写一个dao层接口的实现类
public class UserDaoImpl implements UserDao {
// 需要向dao实现类中注入SqlSessionFactory
// 这里通过构造方法注入
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById", id);
// 释放资源
sqlSession.close();
return user;
}
@Override
public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行插入操作
sqlSession.insert("test.insertUser", user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行插入操作
sqlSession.delete("test.deleteUser", id);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
}
然后就是对我们写的代码的测试
这样开发的话有一些问题:
1.dao接口的实现类中存在大量的重复代码,这些代码会增加程序员的工作量。
2.在实现类中,SqlSession的方法在调用映射文件中的sql语句时将statement的id(其中的"test.findUserById"便是statment的id)硬编码了。
3.调用SqlSession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入的不是Dao方法中的参数类型,在编译的时候也不会报错,不利于程序的开发。
为了解决这些问题,我们通过满足一些规范就将实体层的实现类的开发省去,由mybatis框架提供的代理实现类替我们去动态的调用我们的映射文件,然后去执行类中的方法。
mapper代理方法的原理
这之前,先声明一下,使用mapper代理的时候,命名和之前的不太一样。这里的接口命名由原来的** 改为**Mapper,比如说原来的User接口,现改为UserMapper。其内容和本质没有变,只是换了一个命名规范。除了接口外映射文件也是由User.xml改为UserMapper.xml其内容不变。
mapper代理方法的思路是,程序员接着写持久层的接口。
和对应每个接口的配置文件。
在我们的原来的方法中需要再写一个接口的实现类,用来构建会话工厂(SqlSessionFactory)和对应的会话(SqlSession)然后通过会话去读取映射文件中的sql语句(这里不准确,不过可以这么理解)。那么我么就可以在这个实体类上做点文章了:
1.我们可以创建一个代理类,在我们相应的接口被调用的时候,代理类就会创建这个对象,创建会话工厂和会话并不难。
2.还有就是我们的sqlSession对象调用的方法名称,这个很好理解,对应的是我们映射文件的标签。
3.那么接下来就是传入参数和接收返回值的问题了:
3.1 传入参数:我们总共需要传入两个参数,一个是映射文件的statement的id的字符串,另外一个是执行需要的参数。 比较困难的是,这个字符串的生成问题。我们的每个方法到底对应的是哪个映射文件的statement的id。对于这个问题,mybatis给出了我们的解决方法:我们的实体层对象读到的字符串是这样的:test.insertUser
可以将这个id分为两部分,其中的test是我们的映射文件中的namespace的值,这个值让它和持久层接口的地址一致,这样就使得代理对象可以通过接口的地址动态的生成id的前半部分,也就是test的这一部分;而后半部分则是让映射文件中的Statement的id和接口的方法一致。
也就是说,用户在调用接口的某一个方法的时候,mybatis可以根据接口地址和对应的方法名生成sqlsession对象的方法传入的字符串。这样就解决了传入参数中的字符串的问题了。
还有就是第二个问题:我们的传入具体参数,mybatis规定,传入参数类型必须和接口的传入参数类型一致。这样,我们的传入参数类型就搞定了。
3.2传入参数搞定了以后,返回值也就搞定了,跟传入参数的规定一样,返回值的类型要求和接口返回值一致,这样就可以在代理类中将返回值传出了。
这些搞定了,我们就可以使用代理对象代替我们的实体层具体实现类了。
至此,这些问题就差不多都解决了,不过还有一个问题:我们的select方法返回值问题,代理对象到底是用selectont方法去查询数据库呢还是使用selectlist方法呢?这个跟我们的接口(mapper)的返回值类型有关——如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库;如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。
mapper代理方法
原理讲完了,使用其实就基本上没啥要说的了。
首先我们要创建一个接口。
然后写对应接口的xml文件(截取部分,namespace处就不截图了)。
最后别忘了在SqlMapConfig.xml文件中加载UserMapper.xml。
测试,这里有必要说一下,我们的代理对象是通过SqlSession.getMapper(接口字节码文件)获取的。:
至此,我们的mybatis的实体层的实体层实现类就可以省略不写了。不过这样做的坏处是加强了代码的耦合性,每个接口和每个映射文件必须对应。不过还是感觉通过遵守一定的规范而使得代码量大大减少更爽呢。
mybatis入门-mapper代理原理的更多相关文章
- mybatis的Mapper代理原理
前言:在mybatis的使用中,我们会习惯采用XXMapper.java+XXMapper.xml(两个文件的名字必须保持一致)的模式来开发dao层,那么问题来了,在XXMapper的文件里只有接口, ...
- mybatis入门--mapper代理方式开发
不使用代理开发 之前,我们说了如何搭建mybatis框架以及我们使用mybatis进行简单的增删改查.现在,我们一起来构建一个dao层的完整代码.并用@test来模拟service层对dao层进行一下 ...
- Mybatis非mapper代理配置
转: Mybatis非mapper代理配置 2017年04月26日 20:13:48 待长的小蘑菇 阅读数:870 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog. ...
- Mybatis的mapper代理开发方法
一.开发规范 1.映射文件中的namespase等于mapper接口类路径 2.statement的id与mapper中的方法名一致 3.让mapper的接口方法输入参数类型与statement中的p ...
- Spring+SpringMVC+Mybatis大整合(SpringMVC采用REST风格、mybatis采用Mapper代理)
整体目录结构: 其中包下全部是采用mybatis自动生成工具生成. mybatis自动生成文件 <?xml version="1.0" encoding="UTF- ...
- mybatis——使用mapper代理开发方式
---------------------------------------------------------------generatorConfig.xml------------------ ...
- Mybatis的mapper代理开发dao方法
看完了之前的mybatis原始的dao开发方法是不是觉得有点笨重,甚至说没有发挥mybatis 作为一个框架的优势.总结了一下,原始的dao方法有以下几点不足之处 dao接口实现方法中存在大量的模板方 ...
- springboot集成下,mybatis的mapper代理对象究竟是如何生成的
前言 开心一刻 中韩两学生辩论. 中:端午节是属于谁的? 韩:韩国人! 中:汉字是谁发明的? 韩:韩国人! 中:中医是属于谁的? 韩:韩国人! 中:那中国人到底发明过什么? 韩:韩国人! 前情回顾 M ...
- mybatis的mapper代理,SqlMapConfig.xml中配置,输入和输出映射使用案例
public class User { private int id; private String username;// 用户姓名 private String sex;// 性别 private ...
随机推荐
- (简单) POJ 3159 Candies,Dijkstra+差分约束。
Description During the kindergarten days, flymouse was the monitor of his class. Occasionally the he ...
- shell vim--处理二进制文本
1 使用vim -b :%!xxd 参考:http://www.cnblogs.com/killkill/archive/2010/06/23/1763785.html 2 使用xxd命令 htt ...
- html元素被隐藏在后面
当有些html元素是由于某些控件生成的,然后它被隐藏在其他元素的后面,但是它一开始是隐藏的,你无法直接在html或js里修改它的属性:z-index,使其可以放在更前面,这时可以在css里重新定义控件 ...
- width这样读取出来是一个字符串,并且带有单位,但是offsetwidth返回的是一个数值。
<!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <title> ...
- 【转】git命令
Git使用 1. git pull 更新服务器代码到本地a). git pull origin master是将origin这个版本库的代码更新到本地的master主分支 2. git push ...
- mongodb学习(一)
重点是踏出第一步: 1. 各种资料集合,mongodb的介绍,安装,破解...内容大同小异... http://www.cnblogs.com/kuochin/p/3599630.html;http: ...
- PHPEXCEL实例-导出EXCEL
PHPExcel 是相当强大的 MS Office Excel 文档生成类库,当需要输出比较复杂格式数据的时候,PHPExcel 是个不错的选择. <?php /* * 导出EXCEL * ...
- SVN 备忘录
上传文件夹 svn import distcomp/ svn+ssh://USERNAME@166.120.110.119/mnt/disk1/fserver/svn/distcomp -m &quo ...
- 安装oracle后不能连接问题
在安装oracle之前,还特意找了几篇博客和百度经验看过,因为知道oracle的只能安装一次,如果装不上,OK,基本排除安装的可能了(安装的残留文件卸不完) 然而,我的问题没有出在这里,安装很顺利,一 ...
- Quartz2D 之 简单使用
1. 获取Graphics Context CGContextRef ctx = UIGraphicsGetCurrentContext(); 2. 最后的渲染接口 CGContextStrokePa ...