Mybatis学习总结(二)——Mapper代理开发
一、概要
1、原始DAO开发中存在的问题:
(1)DAO实现方法体中存在很多过程性代码。
(2)调用SqlSession的方法(select/insert/update)需要指定Statement的id,存在硬编码,不利于代码维护。
2、Mapper动态代理方法:程序员只需要写dao接口(Mapper),而不需要写dao实现类,由mybatis根据dao接口和映射文件中statement的定义生成接口实现类代理对象。
3、目标:通过一些规则让mybatis根据dao接口和映射文件中statement的定义生成接口实现代理对象。
二、开发规范
1、在XXXmapper.xml中namespace等于mapper接口地址(即mapper.xml文件中的namespace与mapper.java接口的类路径相同)。

2、XXXmapper.java接口中的方法和mapper.xml中的statement的Id一致。
3、mapper.java接口中的方法输入参数和mapper.xml中statement的parameterType指定的类型一致。
4、mapper.java接口中的方法的返回值类型和mapper.xml中statement的resultType指定的类型一致。


注:以上的开发规范主要是对下面的代码进行统一生成
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById", id);
......
三、UserMapper.java类代码(接口文件)
package com.mybatis.mapper; import java.util.List; import com.mybatis.entity.User; /**
* 用户管理mapper接口
* @author lxx
*
*/
public interface UserMapper { /** 根据ID查询用户信息 */
public User findUserById(int id); /** 根据用户名称模糊查询用户信息 */
public List<User> findUserByName(String username); /** 添加用户 */
public void insertUser(User user); /** 根据ID删除用户 */
public void deleteUser(Integer id); /** 根据ID更新用户 */
public void updateUser(User user); }
四、将原来的User.xml拷贝并修改名称为UserMapper.xml,再将UserMapper.xml文件中的namespace改为mapper接口地址
<!-- namespace命名空间,作用就是对sql进行分类化的管理,理解为sql隔离
注意:使用mapper代理开发时,namespace有特殊作用
-->
<mapper namespace="com.mybatis.mapper.UserMapper">
注:namespace=mapper接口地址
五、在SqlMapConfig.xml中加载UserMapper.xml
<!-- 加载映射文件 -->
<mappers>
<mapper resource="com/mybatis/mapping/User.xml"/>
<mapper resource="com/mybatis/mapping/UserMapper.xml"/>
</mappers>
六、JUnit测试UserMapperTest.java
package com.mybatis.test; import java.io.InputStream;
import java.util.Date;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test; import com.mybatis.entity.User;
import com.mybatis.mapper.UserMapper; public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; // 此方法是在执行@Test标注的方法之前执行
@Before
public void setUp() throws Exception {
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建SqlSessionFcatory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} @Test
public void testFindUserById() {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建Usermapper对象,mybatis自动生成mapper代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findUserById(1);
System.out.println(user);
sqlSession.close();
} @Test
public void testFindUserByName() {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建Usermapper对象,mybatis自动生成mapper代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> list = mapper.findUserByName("小");
System.out.println(list);
sqlSession.close();
} @Test
public void testInsertUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建Usermapper对象,mybatis自动生成mapper代理对象
User user = new User();
user.setUsername("小东");
user.setSex("1");
user.setAddress("天津");
user.setBirthday(new Date());
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.insertUser(user);
sqlSession.commit();
sqlSession.close();
} @Test
public void testUpdateUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建Usermapper对象,mybatis自动生成mapper代理对象
User user = new User();
user.setId(2);//必须设置Id
user.setUsername("小刘");
user.setSex("1");
user.setAddress("北京海淀");
user.setBirthday(new Date());
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.updateUser(user);
sqlSession.commit();
sqlSession.close();
} @Test
public void testDeleteUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建Usermapper对象,mybatis自动生成mapper代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser(3);
sqlSession.commit();
sqlSession.close();
} }
原来这个sqlSession可以自动创建一个mapper接口的代理对象!我们只需要把刚刚写好的mapper接口类的字节码对象传给getMapper方法,即可得到一个该接口对应的代理对象,然后我们就可以使用这个代理对象来操作接口中具体的方法了。
到这里,使用mapper代理的方式开发dao就总结完了,但是有个小细节,由于mapper接口中方法的参数要根据映射文件中的parameterType来指定,而parameterType只有一个,所以mapper接口中所有方法的参数都只有一个!那如果我们要传入两个或多个参数该咋整?这没办法,想要传多个参数还是死了这条心了吧,但是可以解决这个问题,就是对传入的对象进行增强,让传进去的对象包含我们需要的参数即可。这算是个小弊端吧,但是不会影响我们开发。
七、小结
1、用mapper代理开发时只要写2个:
(1)mapper.xml
(2)mapper接口
2、Mapper接口开发需要遵循以下规范:
(1)Mapper.xml文件中的namespace与mapper接口的类路径相同。
(2)Mapper接口方法名和Mapper.xml中定义的每个statement的id相同。
(3)Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同。
(4)Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。
3、代理对象内部调用selectOne()和selectList():
如果mapper对象返回单个pojo对象(非集合对象)代理对象内部通过selectOne查询数据库,如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。
4、mapper接口中的方法参数只能有一个是否影响系统开发,mapper接口方法参数只能有一个,系统是否不利于维护?
回答:系统框架中,dao层的代码是被业务层公用的。mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。
Mybatis学习总结(二)——Mapper代理开发的更多相关文章
- 【MyBatis学习04】mapper代理方法开发dao
上一篇博文总结了mybatis使用 原始dao的方法存在的一些弊端,我们肯定不会去用它,那么mybatis中该如何开发dao呢?如题所述,这篇博文主要来总结一下使用mapper代理的方法来开发dao的 ...
- Spring+SpringMVC+MyBatis深入学习及搭建(二)——MyBatis原始Dao开发和mapper代理开发
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6869133.html 前面有写到Spring+SpringMVC+MyBatis深入学习及搭建(一)——My ...
- mybatis入门基础(二)----原始dao的开发和mapper代理开发
承接上一篇 mybatis入门基础(一) 看过上一篇的朋友,肯定可以看出,里面的MybatisService中存在大量的重复代码,看起来不是很清楚,但第一次那样写,是为了解mybatis的执行步骤,先 ...
- 【转】Mybatis学习---MyBatis知识、原始Dao开发和mapper代理开发
[原文]https://www.toutiao.com/i6594610137560777223/ 一.什么是MyBatis MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及 ...
- mybatis 学习笔记(三):mapper 代理开发 dao 层
mybatis 学习笔记(三):mapper 代理开发 dao 层 优势 通过使用mapper 代理,我们可以不需要去编写具体的实现类(使用 getMapper() 方法自动生成),只需编写接口即可, ...
- 【mybatis深度历险系列】深入浅出mybatis中原始dao的开发和mapper代理开发
使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法.mybatis在进行dao开发的时候,涉及到三姐妹,分别是SqlSessionFactoryBuilder ...
- mybatis学习记录二——mybatis开发dao的方法
4.1 SqlSession使用范围 4.1.1 SqlSessionFactoryBuilder 通过SqlSessionFactoryBuilder创建会话工厂SqlSession ...
- mybatis学习第(二)天
Mybatis第二天 高级映射 查询缓存 关于与spring的整合和反转工程我偷懒了,下次看. 使用的sql: CREATE TABLE USER( id INT PRIMARY KEY A ...
- Mybatis学习总结二
Mapper动态代理开发方式 实现原理: Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象. Mapper接口开发需 ...
随机推荐
- CTO 之“六脉神剑”
他深谙电商之道,从零打造 1 号店网站及供应链系统,以技术引领业务发展.他是欧电云创始人韩军,下面将由他分享完美 CTO “六脉神剑”的经验之谈. 首先,从对 CTO 的一个认识误区讲起. 不写代码的 ...
- java.io.IOException No space left on device
磁盘空间不足 1.df -k,发现程序所在的工作目录/data,居然到了100%. 1604050 free allocated Kb 535144219 used allocated Kb 100 ...
- 如何用原生JS实现一个简单的promise
我又又又回来了,最近真是累的跟狗一样,急需一个大保健回复一下子精力 我现在是一边喝着红牛一边写着博客,好了好了,不扯了,回归整体好吧 先简单来说一下啥是promise吧 它是什么?Promise是一个 ...
- docker 安装jenkins
基于docker 进行安装 软件,首先需要有docker环境. 1.docker 下载 jenkins 镜像 指定版本 ,因为低版本的后面安装 软件会失败(亲测). docker pull jenki ...
- win7x64上配置 vs2015
win7 x64配置vs2015成功关键 1. 首先查看win7版本是否是sp1或以上: [计算机]----->[属性] 2. 将IE浏览器升级到IE11: IE11[百度网盘下载],提取码:[ ...
- MySQL数据库导入错误:ERROR 1064 (42000) 和 ERROR at line xx: Unknown command '\Z'.
使用mysqldump命令导出数据: D:\Program Files\MySQL\MySQL Server 5.6\bin>mysqldump -hlocalhost -uroot -proo ...
- C#中禁止跨线程直接访问控件
C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它.此时它将会在内部调用ne ...
- 精通initramfs构建step by step
(一)hello world 一.initramfs是什么 在2.6版本的linux内核中,都包含一个压缩过的cpio格式 的打包文件.当内核启动时,会从这个打包文件中导出文件到内核的rootfs ...
- C#重试公用类
//Retry机制 public static class RetryExecutor { /// <summary> /// 重试零个参数无返回值的方法 /// </summary ...
- python第五十一天----线程,Event,队列
进程与线程的区别: 线程==指令集,进程==资源集 (线程集) 1.同一个进程中的线程共享内存空间,进程与进程之间是独立的 2.同一个进程中的线程是可以直接通讯交流的,进程与间通讯必需通过一个中间的 ...