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 ...
随机推荐
- Spring简单属性注入--不常用!!!
UserDAOImpl.java: package com.bjsxt.dao.impl; import com.bjsxt.dao.UserDAO; import com.bjsxt.model.U ...
- hibernate---性能优化, 1+N问题
session级缓存 保存一个hashmap, 读出来的对象放在里面, 如果读出来50条放50条, 如果另起session原来的50条就被清除.可以手动session.clear清除. 如果同一个se ...
- mysql 数据库 切表的脚本
#!/bin/sh host=$1 port=$2 host=${host:="localhost"} #host没赋值,那么就赋值为localhost port=${port: ...
- LPC1788的IIC使用
#ifndef __IIC0_H_ #define __IIC0_H_ #include "common.h" #include "delay.h" //IIC ...
- 起步X5 的铛铛的安装部署过程
(2017年1月)主要资料: 1.铛铛的IM Server即时通信服务使用 actor https://github.com/actorapp/actor-platform ,开发者网站是:htt ...
- Hibernate 中对象关系映射(ObjectRelationMapping)
1.什么是对象关系映射? 解析:对象-关系映射(Object Relational Mapping,简称ORM,对象关系映射)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说, ...
- java 正则匹配int型
private static Pattern DIGIT_PATTERN = Pattern.compile("=\\d++"); Matcher goodsTypeMatcher ...
- Linux命令之文件处理
文件处理命令 1.dirname命令 dirname命令去除文件名中的非目录部分,仅显示与目录有关的内容.dirname命令读取指定路径名保留最后一个/及其后面的字符,删除其他部分,并写结果到标准输出 ...
- bzoj2120: 数颜色 &&bzoj2453: 维护队列
题目大意: 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好 ...
- 如何解决Ajax跨域问题-1
如何解决Ajax跨域问题 最近在做AJAX调用C的问题,出现跨域问题,学习总结如下: 在做ajax读取数据的时候,经常会遇到ajax需要跨域的问题,但由于浏览器安全方面的限制,XMLHttpReque ...