MyBatis动态代理和映射器

news2024/11/15 10:58:24

目录

1、映射器简介

(1)什么是mapper动态代理?

(2)动态代理的规范

(3)如何使用动态代理

(4)为什么学映射器

(5)映射器与接口

(6)映射器的引入

(7)映射器的组成

2、select元素

(1)select元素结构

(2)示例代码

(3)输出pojo对象,简单参数,pojo参数

(4)多个参数传递

3、insert元素

(1)insert元素结构

(2)主键回填

4、update元素和delete元素

(1)update元素

(2)delete元素

5、resultMap元素

(1)为什么要使用resultMap元素

(2)resultMap元素的结构

(3)使用POJO存储结果集

6、多表联查

(1)什么是联查

(2)一对一级联步骤

(3)一对一级联映射

(4)一对多级联步骤

(5)一对多级联

(6)级联的缺陷


1、映射器简介

(1)什么是mapper动态代理?

        在接口中有方法的返回值定义,参数的定义,方法名,在sqlMapper.xml中也对应这接口给予了赋值,这时候dao的实现类就显得多余,这是Mybatis可以帮助我们自动产生实现类,并可以调取方法得到结果,这就是Mybatis的mapper动态代理。

(2)动态代理的规范

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

        相当于是你在Mapper层声明方法,在xml中去实现sql代码逻辑。

        相当于是一个接口文件对应一个xml文件,而且必须名字相同

        也就是方法名和id名也必须相同才能映射到,Mapper接口开发需要遵循以下规范:

  • Mapper.xml文件中的namespace与mapper接口的类路径相同
  • Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
  • Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
  • Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

(3)如何使用动态代理

        使用SqlSession的方法getMapper()让Mybatis自动生成对应接口的实现对象。

        首先是DaoUtil层,它封装了一些加载配置文件、构建工厂、创建SqlSession对象等操作和关闭资源等操作。

public class DaoUtil {
	private static SqlSessionFactory factory;
	static {
		try {
			// 1.加载配置文件
			// 加载 MyBatis 配置文件 mybatis-config.xml。配置文件中包含了数据库连接信息和 MyBatis 的各种设置
			InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
			// 2.构建工厂
			factory = new SqlSessionFactoryBuilder().build(stream);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static SqlSession getSqlSession() {
		// 从 SqlSessionFactory 中打开一个新的 SqlSession。SqlSession 是 MyBatis 的核心接口之一,用于执行 SQL 命令、获取映射器以及管理事务。
		return factory.openSession();
	}

	public static void closeResource(SqlSession sqlSession) {
		// 释放资源
		sqlSession.close();
	}

}

        然后是测试类中,调用DaoUtil方法来实现动态代理的使用。

public static void main(String[] args) {
		SqlSession sqlSession = DaoUtil.getSqlSession();

		StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);

		List<Student> blist = stuMapper.findAllStudentAndClassOneTable(2);
		
		for(Student s : blist) {
			System.out.println(s);
		}
		
		DaoUtil.closeResource(sqlSession);
	}

        其中包含的方法有:

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

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

(4)为什么学映射器

        半自动化的体现:配置 SQL 语句,体现了半自动化和灵活性。

        ORM的体现:对象关系映射的实现,数据库表和POJO类的映射关系。

(5)映射器与接口

         映射器配置文件和接口绑定:配置文件名对应接口名,id属性值对应方法名。

(6)映射器的引入

        文件路径:用相对路径引入映射器

<mapper resource = ”com/codeup/dao/Mapper.xml”/>

        XML:用文件定位符引入映射器

<mapper url = ”file:///var/mappers/Mapper.xml”/>

        包名:用包名引入映射器

<package name = ”com.codeup.dao.Mapper”/>

        类注册:用类名引入映射器

<mapper class = ”com.codeup.mapper.NewsMapper”/>

(7)映射器的组成

2、select元素

(1)select元素结构

属性说明
id唯一标识,接口中的方法名;
parameterType参数的类型;
resultType结果的类型;
resultMap复杂的结果集映射关系;
(2)示例代码

        通过班级编号来查询一个学生:

        StudentMapper接口封装的抽象方法:

public Student findStudentBySid(int sid);

        StudentMapperXML对应的映射器XML代码中:

<select id = "findStudentByClassid" parameterType="int" resultType="student"> 
		select * from student where classid = #{v}
</select>

        这里的id就是接口抽象方法的方法名,parameterType对应的就是传进来的参数(要查找几班的学生),resultType就是返回的类型(查询到的具体学生)。

        #{v}是用来处理参数占位符的。它会将传入的参数值安全地替换到 SQL 语句中,防止 SQL 注入攻击。在XML文件中,配置文件中利用 parameterType 属性设置参数类型,利用 #{}设置参数的使用及位置。在接口中,接口中,按照方法的入参方式指定参数类型和参数名称。

(3)输出pojo对象,简单参数,pojo参数

        在使用 MyBatis 或 Hibernate 等 ORM 框架时,POJO 类通常表示数据库中的表记录

        在我们写XML映射器代码时会有一些逻辑的判断,但是在XML中不能用java中的常规条件符号来写,需要用替换符号来完成逻辑的判断。

        如果条件有 > < >= <= 可以使用转义字符进行代替:

         示例代码:

<select id="findStudentBigSid" parameterType="int" resultType="student">
		select * from student where sid &lt; #{v}
</select>

        例如这段代码用&lt就可以实现查找小于指定sid的学生信息。

(4)多个参数传递

        方法1:Map方式(不推荐 耦合度太高

        比如说现在我们有一个对学生进行查询并且以表联查的方式对应着学生班级一对一查询,再对其结果进行分页,但是我们的映射器parameterType只能传入一个参数,呢该怎么办呢,这时候就可以传入一个Map集合,把我们想要传进入的值都放在Map里面。

        接口代码:

public List<Student> findStudentByClassidAndSsexLimit(Map<String, Object> map);

        XML代码:

<select id="findStudentByClassidAndSsexLimit" parameterType="map" resultType="student">
		select * from student where classid = #{bj} and ssex = #{xb} limit #{wz},#{bc}
</select>

        这里就将map传递进入,按照map传进去的不同的类型,对应着完成sql语句的拼接。但是如果表结构发生变化,或者参数名称改变都会要重新维护代码,所以耦合度很高

        

        方法2:JavaBean方式(推荐,但只能查看实体类所有属性值)

        如果你要通过班级id和性别来查看一个学生的信息,呢我们完全可以实例化一个学生对象,通过给里面的参数赋值来传入映射其中,完成查询。

        接口代码:

public List<Student> findStudentByClassidAndSsex(Student s);

        XML代码:

<select id = "findStudentByClassidAndSsex" parameterType="student" resultType="student">
		select * from student where classid = #{classid} and ssex = #{ssex}
</select>

        方法3:param数 (推荐,Map和key固定)

        可以通过param数来进行传递多参,param相当于Map但是它的key是固定的,值不是固定的,key从1开始往后递增。

        接口代码:

public List<Student> findStudentByClassidAndSsexlimitParam(int classid, String sex, int weizhi, int buchang);

        XML代码:

<select id="findStudentByClassidAndSsexlimitParam">
		select * from student where classid = #{param1} and ssex = #{param2} limit #{param3},#{param4}
</select>

        方法4:arg数(不推荐)

        可以通过arg数来进行传递多参,从0开始依次递增。

        接口代码:

public List<Student> findStudentByClassidAndSsexlimitArg(int classid, String sex, int weizhi, int buchang);

        XML代码:

<select id="findStudentByClassidAndSsexlimitArg" resultType="student">
		select * from student where classid = #{arg0} and ssex = #{arg1} limit #{arg2},#{arg3}
</select>

3、insert元素

(1)insert元素结构

属性说明
id唯一标识,接口中的方法名;
parameterType参数的类型;
keyProperty表示以哪个列作为属性的主键,不能和 keyColumn 同时使用;
keyColumn指明哪一列是主键,不能和 keyProperty同时使用;
useGeneratedKeys使用 JDBC 的 getGeneratedKeys 方式来取有数据库内部生成的主键;
(2)主键回填

        主键回填就是当主键在数据库中为自增字段时,新增成功后,回填主键。相当于有把主键值返回给了当前的实体类对象。

        两个属性:useGeneratedKeys="true" 开启主键回填,keyProperty="sid" 回填的主键给哪个属性。

        自定义主键生成规则:

        <selectKey>:用来预先设定主键值。自定义主键生成规则时,可以使用该标签;

        order属性:取值 BEFORE,AFTER ;

4、update元素和delete元素

(1)update元素

属性说明
id唯一标识,接口中的方法名;
parameterType参数的类型;

(2)delete元素

属性说明
id唯一标识,接口中的方法名;
parameterType参数的类型;

5、resultMap元素

        当我们给数据库中的表字段创建实体类时,因为java和数据库的命名规范不同,所以有时候可能会导致字段名和属性不一致的问题。

        其中属性smname和字段名sm_name不一致,会导致映射不上的问题。

(1)为什么要使用resultMap元素

        定义映射规则:ORM的特性,POJO 类和数据库的映射关系;

        级联操作:多表存在主外键关系时,主表和从表之间的关联操作;

        类型转换:数据库字段的类型和 POJO类属性的类型转换。

(2)resultMap元素的结构

(3)使用POJO存储结果集

属性说明
property映射到列结果的字段或者属性,通常是指 POJO 的属性;
column对应的数据库字段;
javaTypeJava 类型,可以是基本数据类型,也可以是类完全限定名;
jdbcTypeJDBC 的类型,基本支持所有常用的数据库类型;

        通常来讲property传入的时java中的属性,而colum代表的是对应的表中的字段名称。

        如果没有做映射处理的话,POJO属性和数据库字段不对应的属性就会显示为null。

        示例代码(错误):

<select id="findAllSMaster" resultType="SMaster">
	select * from schoolmaster
</select>

        查询结果:

        查询的结果smname为null,因为属性名和字段名不对应。

        示例代码(正确):

<resultMap type="smaster" id="sm_map">
	<result column="sm_name" property="smname"></result>
</resultMap>
	
<select id="findAllSMaster" resultMap="sm_map">
	select * from schoolmaster
</select>

        查询结果:

6、多表联查

(1)什么是联查

        级联(cascade),是指多个对象之间的映射关系,建立数据之间的级联关系提高管理效率。

        一对一:一个对象对应唯一的对象,举例:中国公民和身份证;

        一对多:一个对象对应多个对象,举例:班级和学生;

        多对多:多个对象对应多个对象,举例:公司角色和公司员工;

(2)一对一级联步骤

(3)一对一级联映射

        以一个学生为例,一个学生最多对应一个班级,所以一个学生对应一个班级,这就是一对一级联。

        示例代码:

        接口代码:

public List<Student> findAllStudent();

        XML代码:

<resultMap type="student" id="stu_class_Map">
	<result column="sid" property="sid" />
	<result column="sname" property="sname" />
	<result column="birthday" property="birthday" />
	<result column="ssex" property="ssex" />
	<result column="classid" property="classid" />
	<!-- 一对一 -->
	<association property="bj" javaType="Banji">
		<result column="classid" property="classid" />
		<result column="classname" property="classname" />
	</association>
</resultMap>
	
<select id="findAllStudent" resultMap="stu_class_Map">
	select * from student
	left join class on student.classid = class.classid
</select>

        这样查询就可以实现一个学生对应一个班级的查询。<association property="bj">代表的是java中属性名为bj,javaType="Banji"这个代码意思是bj的类型为Banji。这一句用于定义一对一关联关系。

(4)一对多级联步骤

 
(5)一对多级联

        以一个班级为例,一个班级中可以有很多的学生,所以如果要以班级为主表来联查,就得在实体类中创建一个学生列表来存放学生。但是如果单独用映射器来映射的话,只能映射出班级的属性,所以要用一对多的步骤来完成对班级内的所有学生的映射操作。

        示例代码:

        接口代码:

public List<Banji> findAllBanjiAndStu();

        XML代码:

<resultMap type="Banji" id="bj_class_Map">
	<result column="classid" property="classid"/>
	<result column="classname" property="classname"/>
			
	<!-- 1对多 -->
	<collection property="stulist" ofType="Student">
		<result column="sid" property="sid"/>
		<result column="sname" property="sname"/>
		<result column="birthday" property="birthday"/>
		<result column="ssex" property="ssex"/>
		<result column="classid" property="classid"/>
	</collection>
</resultMap>
	
<select id="findAllBanjiAndStu" resultMap = "bj_class_Map">
	select * from class
	left join student on class.classid = student.classid
</select>

        这段代码property是对应java中的属性stulist学生集合,映射的对应属性是student的实体类。

(6)级联的缺陷

        使用建议: 

        根据实际情况增加级联关系;

        多层关联式,建议超过三层关联时尽量少用级联

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

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

相关文章

动手学深度学习V2每日笔记(卷积层)

本文主要参考沐神的视频教程 https://www.bilibili.com/video/BV1L64y1m7Nh/p2&spm_id_from333.1007.top_right_bar_window_history.content.click&vd_sourcec7bfc6ce0ea0cbe43aa288ba2713e56d 文档教程 https://zh-v2.d2l.ai/ 本文的主要内容对沐神提供的代码中个人不…

3.OpenFeign与负载均衡

文章目录 什么是 OpenFegin0penFeign 与 Ribbon.对 consumer 的改造超时配置请求响应的压缩设置选择远程调用的底层实现技术OpenFegin 整合 LoadBalancer 负载均衡负载均衡策略的更换小结 前面消费者对于微服务的消费是通过 RestTemplate 完成的,这种方式的弊端是很明显的:消费…

清华计算几何-算法LowBound和ConvexHull(凸包)-GrahamScan

算法复杂度最低界限LowBound 算法求解复杂度是否存在一个最低界限&#xff0c;有时候想尽一切办法优化一个算法&#xff0c;去优化其复杂度&#xff0c;比如 清华计算几何-ConvexHull(凸包)-求极点InTriangle/ToLeft Test-CSDN博客 清华计算几何-ConvexHull(凸包)-求极边_计…

5.0-软件工程基础知识-考点分析

考试占比大概10分 软件工程概述软件过程模型 瀑布模型 瀑布模型变种-V模型 演化模型-原型模型 增量模型 喷泉模型 基于构件的开发模型 形式化方法模型需求分析系统设计系统测试运维软件质量和度量项目管理系统分析与设计概念结构化分析WebApp设计与用户界面设计

【小技巧】Keil5 和 NotePad++ 代码格式化 (Ctrl + Q) ( 插件安装astyle-3.5-x64 / NppAStyle)

Artistic Style 是适用于 C、C、C/CLI、 Objective-C 、C# 和 Java 编程语言的源代码缩进器、格式化器和美化器。它用 C 编写&#xff0c;可以从命令行使用&#xff0c;也可以作为库合并到另一个程序中。可以从命令行或选项文件输入选项。可以从用 C 以外的语言编写的程序中调用…

【qiankun微前端】基座主应用(vue2)+多个微应用(任意框架)

前言 前段时间对我们已有的工程进行了微前端改造,后来思考一下微前端的本质,查询了不少资料,从qiankun微前端示例中学到了不少。 微前端的核心,似乎应该是一个基座应用(含登录页,layout页,404和首页等),多个子应用(任意框架,提供内部页面内容),下面就对这个思路…

预警器件控制思考

预警器件控制思考 最小示例思想 当读取到环境信息与环境阈值的时候, 我们预警系统就要根据这些信息做出判断,是否要启动器件。 最简单的就是&#xff0c; 举温度temp的例子, temp(温度)与temp_th(阈值), 通过判断, 得出是否要启动器件. 如果在一段时间内, 一直是环境异常, 我…

私藏心术:低谷期翻身转运秘籍

私藏心术&#xff1a;低谷期翻身转运秘籍 在生活中&#xff0c;每个人都可能遇到低谷期&#xff0c;那些看似无法逾越的障碍和挫折。但记住&#xff0c;低谷期不是终点&#xff0c;而是重新站起来的起点。本文将分享一些实用的心术和策略&#xff0c;帮助你在低谷期实现翻身转…

第一个 Flask 项目

第一个 Flask 项目 安装环境创建项目启动程序访问项目参数说明Flask对象的初始化参数app.run()参数 应用程序配置参数 安装环境 mkvirtualenv flask_envpip install flask创建项目 启动程序 访问项目 http://127.0.0.1:5000/ 参数说明 Flask是一个用Python编写的轻量级Web应…

程序员学长 | 快速学习一个算法,CLIP

本文来源公众号“程序员学长”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;快速学习一个算法&#xff0c;CLIP 今天给大家介绍一个强大的算法模型&#xff0c;CLIP。 CLIP (Contrastive Language–Image Pre-training) 是一个…

机器学习流程图

第一部分&#xff1a;课程使用的技术栈 &#xff08;1&#xff09;Numpy 科学计算基础库&#xff0c;矩阵运算&#xff0c;线性代数 &#xff08;2&#xff09;matplotlib 绘图库&#xff0c;数据可视化 &#xff08;3&#xff09;Scikit 封装了各种分类&#xff0c;回归…

【课程总结】day19(下):Transformer源码深入理解

前言 在上一章【课程总结】day19(下):Transformer架构及注意力机制了解总结中,我们对Transformer架构以及注意力机制有了初步了解,本章将结合《The Annotated Transformer》中的源码,对Transformer的架构进行深入理解。 背景 《The Annotated Transformer》是由 Harva…

LaneATT推理详解及部署实现(上)

目录 前言1. 概述2. 环境配置3. Demo测试4. ONNX导出初探5. ONNX导出优化6. ONNX导出总结结语下载链接参考 前言 最近想关注下车道线检测任务&#xff0c;在 GitHub 上找了一个模型 LaneATT&#xff0c;想通过调试分析 LaneATT 代码把 LaneATT 模型导出来&#xff0c;并在 tens…

Java游戏源码:象棋网络对战版

学习java朋友们&#xff0c;福利来了&#xff0c;今天小编给大家带来了一款象棋网络对战版源码。 源码搭建和讲解 源码分为客户端和服务器&#xff0c;采用java原生 java.net.Socket 实现&#xff0c;服务器主循环代码&#xff1a; import java.net.ServerSocket; import jav…

二维码生成原理及解码原理

☝☝☝二维码配图 二维码 二维码&#xff08;Quick Response Code&#xff0c;简称QR码&#xff09;是一种广泛使用的二维条形码技术&#xff0c;由日本公司Denso Wave在1994年开发。二维码能有效地存储和传递信息&#xff0c;广泛应用于商品追溯、支付、广告等多个领域。二维…

Star-CCM+负体积网格检查与出现原因

要使网格可用于有限体积计算&#xff0c;每个网格单元必须具有正体积&#xff0c;否则初始化过程将失败&#xff0c;且模拟计算无法运行。 负体积网格单元可能会以多种不同的方式出现&#xff0c;但必须修复或从网格中移除&#xff0c;才能继续执行任何后续操作。 要检查体网…

<数据集>人员摔倒识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;8605张 标注数量(xml文件个数)&#xff1a;8605 标注数量(txt文件个数)&#xff1a;8605 标注类别数&#xff1a;1 标注类别名称&#xff1a;[fall] 序号类别名称图片数框数1fall860512275 使用标注工具&#xf…

当前生物信息学研究面临的四大机遇和挑战(特别是最后一个,一定要足够重视)...

生物信息学是应用计算方法分析生物数据&#xff0c;如 DNA&#xff0c;RNA&#xff0c;蛋白质和代谢物。生物信息学已成为促进我们对生命科学的理解以及开发新的诊断&#xff0c;治疗和生物技术产品的重要工具。本文我们将探讨生物信息学研究的一些当前趋势和发展&#xff0c;以…

如何快速入门 PyTorch ?

PyTorch是一个机器学习框架&#xff0c;主要依靠深度神经网络&#xff0c;目前已迅速成为机器学习领域中最可靠的框架之一。 PyTorch 的大部分基础代码源于 Ronan Collobert 等人 在 2007 年发起的 Torch7 项目&#xff0c;该项目源于 Yann LeCun 和 Leon Bottou 首创的编程语…

【C++题解】1249. 搬砖问题

欢迎关注本专栏《C从零基础到信奥赛入门级&#xff08;CSP-J&#xff09;》 问题&#xff1a;1249. 搬砖问题 类型&#xff1a;嵌套穷举 题目描述&#xff1a; 36 块砖&#xff0c; 36 人搬。男搬 4 &#xff0c;女搬 3 &#xff0c;两个小儿抬一砖。 要求一次全搬完。问需…