06-Mapper动态代理

Mppaer 动态代理

目录

  • 创建 Mapper 工程
  • 定义接口的要求
  • 测试类
  • Mapper 中参数传递
  • 单个参数
  • 多个参数
  • @param命名参数
  • 多个参数封装成 Map
  • 多个参数之 POJO
  • 参数处理源码分析

 

之前我们一直都使用传统开发模式DAO,即定义接口,然后定义实现类。这个其实是较为繁琐的,MyBatis 中提供了 Mapper 动态代理的方法,操作起来十分简洁,只需要定义满足要求的接口,然后通过 sqlSession 获取到 Mapper对象,便可通过 Mapper 对象调用我们定义的方法。

创建 Mapper 工程

定义接口的要求

  • 1、namespace 必须和 Mapper 接口类路径一致。
    不使用 Mapper 的话,namespace 的值可以自定义。
    在这里插入图片描述

  • 2、id 必须和 Mapper 接口方法名一致。
    不使用 Mapper,使用传统DAO开发模式的话,接口方法名可以自定义。
    在这里插入图片描述在这里插入图片描述

  • 3、parameterType 必须和接口方法参数类型一致。
    这个很好理解,传入参数的类型要一样。
    在这里插入图片描述在这里插入图片描述

  • 4、resultType 必须和接口方法返回值类型一致
    这个也很好理解,返回值类型要一样。
    在这里插入图片描述
    在这里插入图片描述

映射文件 Customer.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="myTest"><!--根据cust_id查询客户--><select id="queryCustomerById" parameterType="Int" resultType="com.itlike.domain.Customer">SELECT * FROM `customer` WHERE cust_id  = #{cust_id}</select><!--查询所有的客户,不需要参数--><select id="queryAllCustomer" resultType="com.itlike.domain.Customer">SELECT * FROM `customer`</select><!--根据用户名模糊查询客户--><select id="queryCustomerByName" parameterType="String" resultType="com.itlike.domain.Customer">SELECT * FROM customer WHERE cust_name LIKE '%${value}%';</select><!--添加客户--><insert id="insertCustomer" parameterType="com.itlike.domain.Customer">/*获取插入的最后一个id*/<selectKey keyColumn="cust_id" resultType="Integer" order="AFTER">SELECT last_insert_id()</selectKey>INSERT INTO `customer` (cust_id, cust_name, cust_profession, cust_phone, email)VALUES (#{cust_id}, #{cust_name}, #{cust_profession}, #{cust_phone}, #{email});</insert><!--更新--><update id="updateCustomer" parameterType="com.itlike.domain.Customer">UPDATE `customer` SET cust_name = #{cust_name} WHERE cust_id = #{cust_id}</update><!--删除--><delete id="deleteCustomer" parameterType="com.itlike.domain.Customer">DELETE FROM `customer` WHERE cust_id = #{cust_id}</delete>
</mapper>

Mapper 类:

/*使用 Mapper 动态代理:1.namespace 必须和 Mapper 接口类路径一致2.id 必须和 Mapper 接口方法名一致3.parameterType 必须和接口方法参数类型一致4.resultType 必须和接口方法返回值类型一致
**/
public interface CustomerMapper {// 根据 cust_id 查询客户public Customer queryCustomerById(Integer id);// 查询所有public List<Customer> queryAllCustomer();// 根据用户名模糊查询客户public List<Customer> queryCustomerByName(String name);// 添加客户public void insertCustomer(Customer customer);// 更新public void updateCustomer(Customer customer);// 删除public void deleteCustomer(Customer customer);}

测试类

在 Test 包中 MyTest2.java 中编写一个测试方法:
只要按规范定义好了接口,根据 sqlSession 可以直接获取到 Mapper 对象,可以直接用 Mapper 对象调用接口中的方法。

public void test2(){SqlSession sqlSession = MybatisUtils.openSession();CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);List<Customer> customers = mapper.queryAllCustomer();for (Customer customer : customers) {System.out.println(customer);}sqlSession.close();
}

运行结果:成功查询出数据库中所有的数据。

Opening JDBC Connection
Created connection 422392391.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@192d3247]
==>  Preparing: SELECT * FROM `customer` 
==> Parameters: 
<==    Columns: cust_id, cust_name, cust_profession, cust_phone, email
<==        Row: 1, 鲁班, 射手, 13499887733, 12341241@qq.com
<==        Row: 2, 李白, 刺客, 18977665521, libai@163.com
<==        Row: 3, 阿轲, 刺客, 18977665997, aike@qq.com
<==        Row: 4, 德玛西亚, 肉盾, 13700997665, demaxiya.126.com6
<==        Row: 5, 亚索, 战士, 13586878987, yasuo@qq.com
<==        Row: 6, 奶妈, 辅助, 13398909089, nama@qq.com
<==        Row: 7, 剑圣, 刺客, 13398909088, jiansheng@163.com
<==        Row: 8, 盖伦, 肉盾, 15923242231, gailun@126.com
<==        Row: 9, 锤石, 辅助, 13398908900, 8888@163.com
<==        Row: 11, 孙悟空, 战士, 13728964922, lixin@qq.com
<==        Row: 20, 后裔6, null, 18937485936, null
<==        Row: 21, 后裔6, null, 18937485936, null
<==      Total: 12
Customer{cust_id=1, cust_name='鲁班', cust_profession='射手', cust_phone='13499887733', email='12341241@qq.com'}
Customer{cust_id=2, cust_name='李白', cust_profession='刺客', cust_phone='18977665521', email='libai@163.com'}
Customer{cust_id=3, cust_name='阿轲', cust_profession='刺客', cust_phone='18977665997', email='aike@qq.com'}
Customer{cust_id=4, cust_name='德玛西亚', cust_profession='肉盾', cust_phone='13700997665', email='demaxiya.126.com6'}
Customer{cust_id=5, cust_name='亚索', cust_profession='战士', cust_phone='13586878987', email='yasuo@qq.com'}
Customer{cust_id=6, cust_name='奶妈', cust_profession='辅助', cust_phone='13398909089', email='nama@qq.com'}
Customer{cust_id=7, cust_name='剑圣', cust_profession='刺客', cust_phone='13398909088', email='jiansheng@163.com'}
Customer{cust_id=8, cust_name='盖伦', cust_profession='肉盾', cust_phone='15923242231', email='gailun@126.com'}
Customer{cust_id=9, cust_name='锤石', cust_profession='辅助', cust_phone='13398908900', email='8888@163.com'}
Customer{cust_id=11, cust_name='孙悟空', cust_profession='战士', cust_phone='13728964922', email='lixin@qq.com'}
Customer{cust_id=20, cust_name='后裔6', cust_profession='null', cust_phone='18937485936', email='null'}
Customer{cust_id=21, cust_name='后裔6', cust_profession='null', cust_phone='18937485936', email='null'}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@192d3247]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@192d3247]
Returned connection 422392391 to pool.

Mapper 中参数传递

单个参数

如果接受的是单个参数,可以接受基本类型,对象类型,集合类型的值。
MyBatis 可直接使用这个参数,不需要经过任何处理。
即,单个参数,参数名字可以自定义。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itlike.mapper.CustomerMapper"><!--根据id查询用户--><select id="getCustomerWithID" parameterType="Integer" resultType="com.itlike.domain.Customer">SELECT * FROM `customer` WHERE cust_id = #{id}</select></mapper>

测试类:

public class MyTest {@Testpublic void test(){SqlSession sqlSession = MybatisUtils.openSession();CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);// 查询id为2的用户Customer customer = mapper.getCustomerWithID(2);System.out.println(customer);sqlSession.close();}
}

运行结果:成功查询到id为2的用户

多个参数

在这里插入图片描述
多个参数时不需要写 parameterType 。
任意多个参数,都会被 MyBatis 重新包装成一个 Map 传入。
Map 的 key 是 param1,param2,arg0,arg1,值就是参数的值。
即,多个参数,参数名字必须是 param1,param2 或者 arg0, arg1。

以下两种写法都对:

<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">SELECT * FROM `customer` WHERE cust_id = #{arg0} AND cust_name = #{arg1}
</select>
<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">SELECT * FROM `customer` WHERE cust_id = #{param1} AND cust_name = #{param2}
</select>

测试类:

public void test(){SqlSession sqlSession = MybatisUtils.openSession();CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);Customer customer = mapper.getCustomerWithID(2, "李白");System.out.println(customer);sqlSession.close();
}

运行结果:

Opening JDBC Connection
Created connection 1122805102.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@42eca56e]
==>  Preparing: SELECT * FROM `customer` WHERE cust_id = ? AND cust_name = ? 
==> Parameters: 2(Integer), 李白(String)
<==    Columns: cust_id, cust_name, cust_profession, cust_phone, email
<==        Row: 2, 李白, 刺客, 18977665521, libai@163.com
<==      Total: 1
Customer{cust_id=2, cust_name='李白', cust_profession='刺客', cust_phone='18977665521', email='libai@163.com'}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@42eca56e]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@42eca56e]
Returned connection 1122805102 to pool.

@param命名参数

为参数使用 @Param 起一个名字,
MyBatis 就会将这些参数封装进 Map 中,key 就是我们自己指定的名字。
即,只要在 CustomerMapper 中使用 @Param 就能使用自定义的名字这个自定义名字只能是 @Param() 括号里写的名字)。

CustomerMapper.java 中:

public interface CustomerMapper {public Customer getCustomerWithID(@Param("id") Integer id, @Param("name") String name);
}

像上面这样,就可以自定义参数名字:

<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">SELECT * FROM `customer` WHERE cust_id = #{id} AND cust_name = #{name}
</select>

测试类:

public void test(){SqlSession sqlSession = MybatisUtils.openSession();CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);Customer customer = mapper.getCustomerWithID(2, "李白");System.out.println(customer);sqlSession.close();
}

运行结果:可以正常查询出结果。

注: 如果使用了 @Param 命名参数,param1,param2 作为参数名称依旧可以使用,但是 arg0, arg1 不可用。

多个参数封装成 Map

我们也可以封装多个参数为 Map,直接传递
在 CustomerMppaer.java 中重载一个参数为 Map 类型的方法:

public interface CustomerMapper {public Customer getCustomerWithID(@Param("id") Integer id, @Param("name") String name);public Customer getCustomerWithID(Map<String, Object> map);
}

测试类:将数据封装到 Map 中,然后将 Map 传入上面重载的方法。

public void test(){SqlSession sqlSession = MybatisUtils.openSession();CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);HashMap<String, Object> hashMap = new HashMap<>(); // 将参数封装到 Map 中hashMap.put("id", 1); hashMap.put("name", "鲁班");Customer customer = mapper.getCustomerWithID(hashMap);System.out.println(customer);sqlSession.close();
}

如果通过 Map 传值,在映射文件中的参数名就必须和 Map 的 key 值相同,如下:

<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">SELECT * FROM `customer` WHERE cust_id = #{id} AND cust_name = #{name}
</select>

多个参数之 POJO

我们可以直接传入 POJO 类,但是参数名必须与业务 POJO 中的字段一致。
在 CustomerMppaer.java 中重载一个参数为 POJO 的方法:

public interface CustomerMapper {public Customer getCustomerWithID(@Param("id") Integer id, @Param("name") String name);public Customer getCustomerWithID(Map<String, Object> map);public Customer getCustomerWithID(Customer customer);
}

映射文件 Customer.xml 中参数名必须与POJO中字段一致

<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">SELECT * FROM `customer` WHERE cust_id = #{cust_id} AND cust_name = #{cust_name}
</select>

测试类:自己创建的对象,必须给它设定好 sql 语句中所需的参数,这里需要给它设置 cust_id 与 cust_name。

public void test(){SqlSession sqlSession = MybatisUtils.openSession();CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);Customer customer = new Customer();customer.setCust_name("李白");customer.setCust_id(2);Customer customer1 = mapper.getCustomerWithID(customer);System.out.println(customer1);sqlSession.close();
}

参数处理源码分析

接收参数后,会把参数给放到一个数组当中,如果是一个参数,内部处理时,会自动把该参数返回。
在这里插入图片描述
如果是多个参数,内部会做判断,判断是否有 @Param 注解。
如果没有注解的话:就直接使用 arg0,arg1…为 key,放到 map 中,并且还会以 param1 和param2… 为 key 放一份到 map 中。
在这里插入图片描述
如果有注解的话: 会使用注解当中的值,替换掉默认的 arg0 和 arg1,使用 @Param 中的值,作为 key 放到一个 map 当中。并且还会以 param1 和 param2… 为 key 放一份到 map 中。
在这里插入图片描述
综上,所以传递多个参数时,无论有没有 @Param ,param1、param2 作为参数名都是可以的当有了 @Param 后,arg0、arg1 便会被替换为 @Param 中的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322403.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core MVC中的 [Required]与[BindRequired]

在开发ASP.NET Core MVC应用程序时&#xff0c;需要对控制器中的模型校验数据有效性&#xff0c;元数据注释(Data Annotations)是一个完美的解决方案。元数据注释最典型例子是确保API的调用者提供了某个属性的值&#xff0c;在传统的ASP.NET MVC中使用的是RequiredAttribute特性…

ES集群管理

转载自 ES集群管理 8 集群管理 ES通常以集群方式工作&#xff0c;这样做不仅能够提高 ES的搜索能力还可以处理大数据搜索的能力&#xff0c;同时也增加了系统的容错能力及高可用&#xff0c;ES可以实现PB级数据的搜索。 下图是ES集群结构的示意图&#xff1a; 从上图总结以下…

【Java探索之旅】我与Java的初相识(完):注释,标识符,关键字

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java入门到精通 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. Java的注释方式二. 标识符三. 关键字四. 全篇总结 &#x1f4d1;前言 在Java编程…

07-MyBatis 核心配置文件

MyBatis 核心配置文件 目录 properties 定义属性及读取属性文件settings 设置运行时行为typeAliases 类型别名定义单个别名批量定义别名typeHandlers 类型处理器Plugins&#xff08;后续有文章专门介绍这个&#xff09;Environments 运行环境databaseIDProvider 定义数据库厂…

Office 365也是.NET Core应用开发新战场

最近有幸阅读了陈希章花了一年时间为国内开发者贡献的《Office 365 开发入门指南》。 虽然早期接触过SharePoint的开发&#xff0c;2007年之后就再也没有接触SharePoint的开发&#xff0c;这次阅读这本书让我重新认识了Office的系统开发技术&#xff0c;让我意识到现在的Office…

jzoj4802-[GDOI2017模拟9.24]探险计划【费用流,拆点】

正题 题目大意 一个nnn行的不完全矩阵第iii行有mi−1mi-1mi−1个格子&#xff0c;然后每个格子有危险度。 每次可以从(i,j)(i,j)(i,j)走到(i−1,j)(i-1,j)(i−1,j)或(i−1,j−1)(i-1,j-1)(i−1,j−1) 求 m次&#xff0c;每个格子和路不可以重复走的最小危险度。m次&#xff0…

08-输出类型

输出类型 目录 输出简单类型输出 Map 类型key:列名 value:列名对应的值key:自己指定的列 value:自定义对象resultMap输出简单类型 CustomerMapper.java&#xff1a;返回值为简单类型。 public interface CustomerMapper {/*查询总数*/public Integer getAccountCustomer();…

在Ubuntu 16.04环境下安装Docker-CE(附视频教程)

“ 任何的课程都逃不开理论的支持”久等了各位&#xff0c;上一篇说Docker开始的消息已经过去了一周多的时间&#xff0c;今天推送的消息是告诉大家视频可以学习了&#xff01;52ABP .NET CORE QQ群 : 633751348大纲Docker的介绍Ubuntu下安装Docker快速体验Docker利用Docker搭…

WebApi client 的面向切面编程

.Net的面向切面编程.Net的服务端应用AOP很常见&#xff0c;在Asp.net MVC与Asp.net WebApi等新框架里到处都有AOP的影子&#xff0c;我们可以把一个服务方法“切”为很多面&#xff0c;日志面、验证面、请求方式处理、接口业务实现等多个面&#xff0c;有一些面可以使用过滤器特…

09-一对多关系建表

多表操作 目录 表之间关系一对多关系建表原则表之间关系 一对一关系&#xff1a;一夫一妻。 一对多关系&#xff1a; 一个部门有多个员工&#xff0c;一个员工只能属于某一个部门。 一个班级有多个学生&#xff0c;一个学生只能属于一个班级。 多对多关系&#xff1a; 一个…

10-多对一左连接查询分步查询(查询所有订单及订单对应的客户)

左连接查询&#xff08;级联查询&#xff09; 回顾一下&#xff1a;左连接查询&#xff0c;将左边表(order)里的全部内容查出&#xff0c;右边表(customer)查满足条件的。 SELECT * FROM order AS o LEFT JOIN customer AS c on o.cust_id c.cust_id;1那么在 MyBatis 中如何…

入门干货之Grpc的.Net 封装-MagicOnion

0x01、Grpc1、介绍Google主导开发的RPC框架&#xff0c;使用HTTP/2协议并用ProtoBuf作为序列化工具&#xff0c;支持多种语言。在.NET Core “大更新” 之前&#xff0c;也就是目前来说还算是个很不错的选择。2、吐槽a、有很多性能比较的文章拿Grpc开涮.b、搭建困难&#xff0c…

11-分步查询懒加载

分步查询——懒加载模式 目录 懒加载模式示例不使用懒加载使用懒加载aggressiveLazyLoadinglazyLoadTriggerMethods所谓懒加载&#xff0c;也称延时加载&#xff0c;是指不一下子加载完全部资源。需要用到哪些资源才去加载这些资源&#xff0c;用不到的资源&#xff0c;就不去…

利用Service Fabric承载eShop On Containers

从模块化到微服务化从Pet Shop 到eShop on Container都是Microsoft在技术演进的路径上给开发者展示.Net的开发能力和架构能力的Sample工程&#xff0c;Petshop的时候更多的是展现应用的分层架构&#xff0c;设计的抽象与模块间的通讯。到了eShop on Container更多的关注在架构设…

12-多对一添加操作(添加新客户及对应的新订单)

多对一添加操作 场景&#xff1a;现在想要添加一个新客户对应一个新订单&#xff0c;那么要怎么来添加呢&#xff1f; 分析&#xff1a;由于添加订单时&#xff0c;客户对订单是一对多的关系&#xff0c;所以添加订单的时候必须要指明一位客户。 要同时添加新客户以及一个新订…

.NET Core+MySql+Nginx 容器化部署

1. 引言上两节我们通过简单的demo学习了docker的基本操作。这一节我们来一个进阶学习&#xff0c;完成ASP.NET Core MySql Nginx的容器化部署。本文是基于CentOS 7.4环境进行演示&#xff0c;示例项目可以访问Docker.NetCore.MySql进行下载。2. Hello MySQL同样我们还是以循序…

HiveSQL常用优化方法全面总结

转载自 HiveSQL常用优化方法全面总结 Hive作为大数据领域常用的数据仓库组件&#xff0c;在平时设计和查询时要特别注意效率。影响Hive效率的几乎从不是数据量过大&#xff0c;而是数据倾斜、数据冗余、job或I/O过多、MapReduce分配不合理等等。对Hive的调优既包含对HiveQL语…

P3597-[POI2015]WYC【矩阵乘法,倍增】

前言 正题 题目链接:https://www.luogu.org/problemnew/show/P3597 题目大意 问第kkk长的路径长度(非简单路径) 解题思路 先考虑kkk比较小时的情况&#xff0c;我们可以求出长度为111的路径&#xff0c;长度为222的路径&#xff0c;然后以此类推找到第一个与前面的和到kkk就…

13-一对多左连接查询分步查询(查询所有客户及客户对应的订单)

查询所有客户以及对应的订单 目录 左连接查询&#xff08;不支持懒加载&#xff09;分步查询&#xff08;支持懒加载&#xff09;左连接查询&#xff08;不支持懒加载&#xff09; 场景&#xff1a;我们想要查询出所有的客户&#xff0c;并且把每个客户对应的订单也查出来。…

实战 | 利用Delta Lake使Spark SQL支持跨表CRUD操作

转载自 实战 | 利用Delta Lake使Spark SQL支持跨表CRUD操作 供稿 | eBay ADI-Carmel Team 作者 | 金澜涛 编辑 | 顾欣怡 本文7309字&#xff0c;预计阅读时间22分钟 导读 本文介绍eBay Carmel团队利用Delta Lake&#xff0c;使Spark SQL支持Teradata的Update/Delete语法。…