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框架根据接口定义创建接口的动态代理对象,代理对 ...
随机推荐
- Spring_boot简单操作数据库
Spring_boot搭配Spring Data JPA简单操作数据库 spring boot 配置文件可以使用yml文件,默认spring boot 会加载resources目录的下的applica ...
- bash: pip: command not found... 解决方法
下载安装wget "https://pypi.python.org/packages/source/p/pip/pip-1.5.4.tar.gz#md5=834b2904f92d46aaa3 ...
- 用Java为Hyperledger Fabric(超级账本)开发区块链智能合约链代码之部署与运行示例代码
部署并运行 Java 链代码示例 您已经定义并启动了本地区块链网络,而且已构建 Java shim 客户端 JAR 并安装到本地 Maven 存储库中,现在已准备好在之前下载的 Hyperledger ...
- bzoj 3759 Hungergame 博弈论+线性基
和nim游戏类似 易证必败状态为:当前打开的箱子中石子异或和为0,没打开的箱子中不存在一个子集满足异或和为0 因为先手无论是取石子还是开箱子,后手都可以通过取石子来使状态变回原状态 所以只需判定是否有 ...
- IOS-QQ第三方登录
iOS QQ第三方登实现 我们经常会见到应用登陆的时候会有QQ,微信,微博等的第三方登陆 如图: 下面我们主要讲一下qq的第三方登陆如何实现 首先,到官网注册: http://wiki.conne ...
- DDD「领域驱动设计」分层架构初探
前言 基于 DDD 传统分层架构实现. 项目 github地址:https://github.com/WuMortal/DDDSample 这个分层架构是工作中项目正在使用的分层架构,使用了一段时间发 ...
- MTCNN算法与代码理解—人脸检测和人脸对齐联合学习
目录 写在前面 算法Pipeline详解 如何训练 损失函数 训练数据准备 多任务学习与在线困难样本挖掘 预测过程 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 主 ...
- CSharpGL(53)漫反射辐照度
CSharpGL(53)漫反射辐照度 本系列将通过翻译(https://learnopengl.com)这个网站上关于PBR的内容来学习PBR(Physically Based Rendering). ...
- 从spring框架中的事件驱动模型出发,优化实际应用开发代码
一.事件起源 相信很多人在使用spring框架进行开发时,都会遇到这样的需求:在spring启动后,立即加载部分资源(例如:spring启动后立刻加载资源初始化到redis中).当我去解决这个问题时发 ...
- 第2章 授权端点(Authorize Endpoint) - IdentityModel 中文文档(v1.0.0)
对于大多数情况,OAuth 2.0和OpenID Connect授权端点的GET请求需要具有许多查询字符串参数. 虽然您可以使用任何方法创建带参数的URL来创建正确的字符串,但RequestUrl类是 ...