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 ...
随机推荐
- MapReduce 表连接
题目描述: 根据给定的关系 child parent Tom Lucy Tom Jack Jone Lucy Jone Jack Lucy Mary Lucy Ben Jack Alice Jack ...
- 微信小程序之----生命周期
在app.js的app()中注册程序 在页面.js中的Page({})中注册页面. 执行效果:
- word2010中,插入-符号-公式显示是灰色的解决办法
在文件选项里点转换,把文档转换成最新格式,也就是2010,因为兼容旧版本模式(比方03,07)的文档是无法使用公式编辑器功能的 步骤: 1.点击“文件” 2.出现下图: 3.点击“转换”图标,将生成最 ...
- .NET中四种常用事物
在一个MIS系统中,没有用事务那就绝对是有问题的,要么就只有一种情况:你的系统实在是太小了,业务业务逻辑有只要一步执行就可以完成了.因此掌握事务 处理的方法是很重要,进我的归类在.net中大致有以下4 ...
- 【贪心】【堆】Gym -100956D - Greedy Game
题意:给定n个物品,每个物品对于A和B来说具有不同的价值,记为ai,bi,两人交替取,A先手,A总是贪心地取当前剩下的物品中,对于他价值最高的,如果有多个,则任取一个.问B在最坏情况下,能取到的物品的 ...
- shell 整理,更新,记录
菜鸟级awk,读取android manifest,把key->value 保存到path.rc. awk -F "name=" '{if(/project path/) p ...
- iOS workspace 依次编译多个工程
目的:当我封装一个framework的时候,需要检验当前的改动,但是又不想编译完framework,又要编译测试工程. 步骤: 1. 选择测试工程 2. Edit Scheme 3. 选中Build- ...
- iOS bug 之 H5 页面没有弹出提示框
描述:在安卓上有提示框,但是在iOS上没有提示框. step 1: 失误,是我没有在正确的位置设置网址. step 2: 修改之后,测试页能弹出提示框,但是正式的页面没有提示框. step 3: 我输 ...
- kafkaspout以及kafkabolt的最简实例
这个实例中有一个KafkaSpout,一个KafkaBolt,一个自定义Bolt QueryBolt.数据流程是KafkaSpout从topic为recommend的消息队列中取出St ...
- CNTV视频回看下载地址
这其实不是新方法了,这个方法早在五六年前大家就在用,至今也没失效.但是五六年前那时候这个方法可以下载到过去三个月内CNTV直播过的视频,而现在只能下到一个星期的.之所以要下载回看版本,是因为比栏目版本 ...