一、引言

通过上一篇mybatis的入门学习,我们已经会使用mybatis实现简单的增删改查,但是我们也发现了用原始Dao开发的一些问题:

  1. Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法

  2. 调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护。

为了解决这些问题,我们采用Mapper动态代理方法来进行开发:程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

二、开发规范

Mapper接口开发需要遵循以下规范:

1、 Mapper.xml文件中的namespace与mapper接口的类路径相同。

2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同

3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

4、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

三、改造

第一步:Mapper.xml(映射文件)

定义mapper映射文件UserMapper.xml,将UserMapper.xml放在config下mapper目录下,效果如下:

文件内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 -->
<mapper namespace="com.yuanqinnan.mapper.UserMapper">
<select id="queryUserById" parameterType="int" resultType="com.yuanqinnan.model.User">
SELECT * FROM `user`where id=#{id}
</select>
<!-- 查询 user 表的所有数据-->
<select id="selectUserAll" resultType="com.yuanqinnan.model.User">
select * from user
</select>
<!--
1、${value}里面必须要写value,不然会报错
2、${}表示拼接 sql 字符串,将接收到的参数不加任何修饰拼接在sql语句中
3、使用${}会造成 sql 注入
-->
<select id="selectLikeUserName" resultType="com.yuanqinnan.model.User" parameterType="String">
select * from user where username like '%${value}%'
</select>
<!--#{}实现-->
<select id="selectLikeUserName2" resultType="com.yuanqinnan.model.User" parameterType="String">
select * from user where username like #{username}
</select>
<!-- 向 user 表插入一条数据 -->
<insert id="insertUser" parameterType="com.yuanqinnan.model.User">
insert into user(id,username,sex,birthday,address)
value(#{id},#{username},#{sex},#{birthday},#{address})
</insert>
<!-- 保存用户 -->
<insert id="saveUser" parameterType="com.yuanqinnan.model.User">
<!-- selectKey 标签实现主键返回 -->
<!-- keyColumn:主键对应的表中的哪一列 -->
<!-- keyProperty:主键对应的pojo中的哪一个属性 -->
<!-- order:设置在执行insert语句前执行查询id的sql,在执行insert语句之后执行查询id的sql -->
<!-- resultType:设置返回的id的类型 -->
<selectKey keyColumn="id" keyProperty="id" order="AFTER"
resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO `user`
(username,birthday,sex,address) VALUES
(#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 根据 id 更新 user 表的数据 -->
<update id="updateUserById" parameterType="com.yuanqinnan.model.User">
update user set username=#{username} where id=#{id}
</update> <!-- 根据 id 删除 user 表的数据 -->
<delete id="deleteUserById" parameterType="int">
delete from user where id=#{id}
</delete>
</mapper>

其他地方未有改动,主要是namespace="com.yuanqinnan.mapper.UserMapper"的修改,现在我们实现这个接口

第二步:UserMapper(接口文件)

新建mapper包,新增接口UserMapper

内容:

public interface UserMapper {

    //查询用户
User queryUserById(int id);
//查询用户列表
List<User> selectUserAll(); //模糊查询
List<User> selectLikeUserName(String username); //新增
void saveUser(User user); }

第三步:加载UserMapper.xml文件

<mappers>
<!-- 映射文件方式1,一个一个的配置-->
<mapper resource="config/sqlmap/User.xml"/>
<mapper resource="config/mapper/UserMapper.xml"/>
</mappers>

测试:

public class MapperTest {
private SqlSessionFactory sqlSessionFactory; @Before
public void init() throws Exception {
// 创建SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 加载SqlMapConfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("config/SqlMapConfig.xml");
// 创建SqlsessionFactory
this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
} @Test
public void testQueryUserById() {
// 获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行查询方法
User user = userMapper.queryUserById(1);
System.out.println(user); // 和spring整合后由spring管理
sqlSession.close();
} @Test
public void testQueryUserByUsername() {
// 获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行查询方法
List<User> list = userMapper.selectLikeUserName("张");
for (User user : list) {
System.out.println(user);
} // 和spring整合后由spring管理
sqlSession.close();
} @Test
public void testSaveUser() {
// 获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 创建保存对象
User user = new User();
user.setUsername("刘备");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("蜀国");
// 执行查询方法
userMapper.saveUser(user);
System.out.println(user); // 和spring整合后由spring管理
sqlSession.commit();
sqlSession.close();
}
}

测试结果与上一篇相同

四、总结

selectOne和selectList

动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。

namespace

mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

Mybatis之旅第二篇-Mapper动态代理方式的更多相关文章

  1. Mybatis框架基础入门(三)--Mapper动态代理方式开发

    使用MyBatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper动态代理开发方法. 原始Dao开发方法需要程序员编写Dao接口和Dao实现类,此方式开发Dao,存在以下问题: Dao方 ...

  2. MyBatis开发Dao层的两种方式(Mapper动态代理方式)

    MyBatis开发原始Dao层请阅读我的上一篇博客:MyBatis开发Dao层的两种方式(原始Dao层开发) 接上一篇博客继续介绍MyBatis开发Dao层的第二种方式:Mapper动态代理方式 Ma ...

  3. Mybatis入门——基础方式的增删该查、mapper动态代理方式的CRUD、类型转换器

    一.基础方式的增删该查: 1.mybatis约定:输入参数parameterType和输出参数resulrType在形式上只能有一个. 2.如果输入/输出参数:是简单类型(8个基本类型加String) ...

  4. mybatis开发Dao的Mapper动态代理方式

    1. 开发规范Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体跟Dao原始方法中接口实现类的方法相 ...

  5. 02.MyBatis在DAO层开发使用的Mapper动态代理方式

    在实际开发中,Mybatis作用于DAO层,那么Service层该如何调用Mybatis Mybatis鼓励使用Mapper动态代理的方式 Mapper接口开发方法只需要程序员编写Mapper接口(相 ...

  6. Mybatis Mapper动态代理方式 typeAliases 别名的使用

    目录结构及配置文件与原始dao方法相比更简便 只需一个UserMapper的接口,放在一起的配置文件,配置文件中namespace的地址确定jdk动态代理的对象 <?xml version=&q ...

  7. Mapper 动态代理方式

    Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法. Mapper接口开发 ...

  8. Mapper动态代理方式

    开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同Dao接口实现类方法. Mapper接 ...

  9. 【Mybatis】-- Mapper动态代理开发注意事项

    1.1. Mapper动态代理方式 1.1.1. 开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对 ...

随机推荐

  1. Linux 6.8 TFS(Taobao File System)使用文档-安装篇

    介绍  TFS(Taobao FileSystem)是一个高可扩展.高可用.高性能.面向互联网服务的分布式文件系统,其设计目标是支持海量的非结构化数据的存储:TFS使用C++语言开发,需要运行在64b ...

  2. Guava新增集合类型-Multimap

    Guava新增集合类型-Multimap 在日常的开发工作中,我们有的时候需要构造像Map<K, List<V>>或者Map<K, Set<V>>这样比 ...

  3. CSS实现核辐射警告标志

    今天做了下360的前端星计划测试题,碰到一个有趣的css题,实现如下图效果,记得上次也是在360面试的时候碰到一个有趣的css实现宝马logo,不得不说360的面试题还是很有创意的. 我一直努力想用一 ...

  4. BZOJ_2764_[JLOI2011]基因补全_DP_高精度

    BZOJ_2764_[JLOI2011]基因补全_DP_高精度 Description 在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对 ...

  5. BZOJ_3669_[Noi2014]魔法森林_LCT

    BZOJ_3669_[Noi2014]魔法森林_LCT Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节 ...

  6. 从零搭建基于golang的个人博客网站

    原文链接 : http://www.bugclosed.com/post/14 从零搭建个人博客网站需要包括云服务器(虚拟主机),域名,程序环境,博客程序等方面.本博客 就是通过这几个环节建立起来的, ...

  7. Python安装和配置

    在我厂呆了快一年,终于等来了转岗机会,而且现在正在调动到新成立的AI战略部门,心里无比欣喜和激动.自己作为一个小白,终于有机会踏入AI领域,离自己的梦想更近了一步,个人感到无比的幸运,仿佛天生就有上天 ...

  8. Spark学习之RDD编程总结

    Spark 对数据的核心抽象——弹性分布式数据集(Resilient Distributed Dataset,简称 RDD).RDD 其实就是分布式的元素集合.在 Spark 中,对数据的所有操作不外 ...

  9. 聊一聊快速排序(Js)

    快速排序 基本思路 双指针+递归分治(本质是一个创建二叉树搜索树的过程) 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据 ...

  10. pins-模块内的代码及资源隔离方案

    随着项目的不断迭代,复杂的业务模块及项目自身的基础技术组件迅速扩张,以往基于单个模块的项目往往显得过于臃肿.代码目录结构,包名混乱,代码模块职责不清晰,耦合度高,不便维护.基础公共组件没有抽取并剥离干 ...