Mybatis之旅第二篇-Mapper动态代理方式
一、引言
通过上一篇mybatis的入门学习,我们已经会使用mybatis实现简单的增删改查,但是我们也发现了用原始Dao开发的一些问题:
Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
调用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动态代理方式的更多相关文章
- Mybatis框架基础入门(三)--Mapper动态代理方式开发
使用MyBatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper动态代理开发方法. 原始Dao开发方法需要程序员编写Dao接口和Dao实现类,此方式开发Dao,存在以下问题: Dao方 ...
- MyBatis开发Dao层的两种方式(Mapper动态代理方式)
MyBatis开发原始Dao层请阅读我的上一篇博客:MyBatis开发Dao层的两种方式(原始Dao层开发) 接上一篇博客继续介绍MyBatis开发Dao层的第二种方式:Mapper动态代理方式 Ma ...
- Mybatis入门——基础方式的增删该查、mapper动态代理方式的CRUD、类型转换器
一.基础方式的增删该查: 1.mybatis约定:输入参数parameterType和输出参数resulrType在形式上只能有一个. 2.如果输入/输出参数:是简单类型(8个基本类型加String) ...
- mybatis开发Dao的Mapper动态代理方式
1. 开发规范Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体跟Dao原始方法中接口实现类的方法相 ...
- 02.MyBatis在DAO层开发使用的Mapper动态代理方式
在实际开发中,Mybatis作用于DAO层,那么Service层该如何调用Mybatis Mybatis鼓励使用Mapper动态代理的方式 Mapper接口开发方法只需要程序员编写Mapper接口(相 ...
- Mybatis Mapper动态代理方式 typeAliases 别名的使用
目录结构及配置文件与原始dao方法相比更简便 只需一个UserMapper的接口,放在一起的配置文件,配置文件中namespace的地址确定jdk动态代理的对象 <?xml version=&q ...
- Mapper 动态代理方式
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法. Mapper接口开发 ...
- Mapper动态代理方式
开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同Dao接口实现类方法. Mapper接 ...
- 【Mybatis】-- Mapper动态代理开发注意事项
1.1. Mapper动态代理方式 1.1.1. 开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对 ...
随机推荐
- Linux 6.8 TFS(Taobao File System)使用文档-安装篇
介绍 TFS(Taobao FileSystem)是一个高可扩展.高可用.高性能.面向互联网服务的分布式文件系统,其设计目标是支持海量的非结构化数据的存储:TFS使用C++语言开发,需要运行在64b ...
- Guava新增集合类型-Multimap
Guava新增集合类型-Multimap 在日常的开发工作中,我们有的时候需要构造像Map<K, List<V>>或者Map<K, Set<V>>这样比 ...
- CSS实现核辐射警告标志
今天做了下360的前端星计划测试题,碰到一个有趣的css题,实现如下图效果,记得上次也是在360面试的时候碰到一个有趣的css实现宝马logo,不得不说360的面试题还是很有创意的. 我一直努力想用一 ...
- BZOJ_2764_[JLOI2011]基因补全_DP_高精度
BZOJ_2764_[JLOI2011]基因补全_DP_高精度 Description 在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对 ...
- BZOJ_3669_[Noi2014]魔法森林_LCT
BZOJ_3669_[Noi2014]魔法森林_LCT Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节 ...
- 从零搭建基于golang的个人博客网站
原文链接 : http://www.bugclosed.com/post/14 从零搭建个人博客网站需要包括云服务器(虚拟主机),域名,程序环境,博客程序等方面.本博客 就是通过这几个环节建立起来的, ...
- Python安装和配置
在我厂呆了快一年,终于等来了转岗机会,而且现在正在调动到新成立的AI战略部门,心里无比欣喜和激动.自己作为一个小白,终于有机会踏入AI领域,离自己的梦想更近了一步,个人感到无比的幸运,仿佛天生就有上天 ...
- Spark学习之RDD编程总结
Spark 对数据的核心抽象——弹性分布式数据集(Resilient Distributed Dataset,简称 RDD).RDD 其实就是分布式的元素集合.在 Spark 中,对数据的所有操作不外 ...
- 聊一聊快速排序(Js)
快速排序 基本思路 双指针+递归分治(本质是一个创建二叉树搜索树的过程) 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据 ...
- pins-模块内的代码及资源隔离方案
随着项目的不断迭代,复杂的业务模块及项目自身的基础技术组件迅速扩张,以往基于单个模块的项目往往显得过于臃肿.代码目录结构,包名混乱,代码模块职责不清晰,耦合度高,不便维护.基础公共组件没有抽取并剥离干 ...