Mybatis框架映射---代码实现(XML配置以及注解形式)

目录

一. 映射关系 1 对 1-映射方式

1.通过xml文件实现映射的一对一关系

总结 :

2.通过注解的方式来实现下面的 1 对 1 的映射关系,实现级联查询

总结:

二. 映射关系多对一

1.通过xml文件实现映射的多对一关系

2.通过注解的方式来实现下面的 多对一 的映射关系,实现级联查询


XML与注解的形式本质都是以XML的形式进行的,只不过注解对XML进行可一个封装。 

映射关系就是你在查询一个表的时候,其中的某个属性对应另外一个表的一条记录,或者多条记录。比如你在查询教师表中的某个教师的信息,同时根据这个教师的工号,你可以查到这个教师所教的班级,以及班级的学生等信息。


一. 映射关系 1 1-映射方式

  映射方式
1. 通过配置 XxxMapper.xml 实现 1 1 [ 配置方式 ]
2. 通过注解的方式实现 1 1 [ 注解方式 ]

1.通过xml文件实现映射的一对一关系

通过配置 XxxMapper.xml 的方式来实现下面的 1 1 的映射关系,实现
联查询 , 通过 person 可以获取到对应的 idencard 信息 

1. 创建 person 表和 idencard 表

CREATE TABLE person
(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL DEFAULT '',
card_id INT ,
FOREIGN KEY (card_id) REFERENCES idencard(id)
)CHARSET utf8;

2. 创建 mybatis_idencard 表
CREATE TABLE idencard
(
id INT PRIMARY KEY AUTO_INCREMENT,
card_sn VARCHAR(32) NOT NULL DEFAULT ''
)CHARSET utf8 ;
INSERT INTO idencard VALUES(1,'5002262001121212');
INSERT INTO person VALUES(1,'长离',1);
SELECT * FROM person;
SELECT * FROM idencard

 3.创建IdenCard类

package com.sn.entity;/*** @author sn*/
public class IdenCard {private Integer id;private String card_sn;public IdenCard() {}public IdenCard(Integer id, String card_sn) {this.id = id;this.card_sn = card_sn;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getCard_sn() {return card_sn;}public void setCard_sn(String card_sn) {this.card_sn = card_sn;}@Overridepublic String toString() {return "IdenCard{" +"id=" + id +", card_sn='" + card_sn + '\'' +'}';}
}

4.创建Person类

package com.sn.entity;/*** @author sn*/
public class Person {private Integer id;private String name;private IdenCard card;public Person() {}public Person(Integer id, String name, IdenCard card) {this.id = id;this.name = name;this.card = card;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public IdenCard getCard() {return card;}public void setCard(IdenCard card) {this.card = card;}@Overridepublic String toString() {return "Person{" +"id=" + id +", name='" + name + '\'' +", card=" + card +'}';}
}

5.创建IdenCardMapper接口

package com.sn.mapper;import com.sn.entity.IdenCard;/*** @author sn*/
public interface IdenCardMapper {//根据 id 获取到身份证public IdenCard getIdenCardById(Integer id);
}

6.创建IdenCardMapper.xml映射文件

<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.IdenCardMapper"><!-- 实现 getIdenCardById --><select id="getIdenCardById" resultType="IdenCard" parameterType="Integer">SELECT * FROM idencardWHERE id=#{id}</select>
</mapper>

7.创建PersonMapper接口

package com.sn.mapper;import com.sn.entity.Person;/*** @author sn*/
public interface PersonMapper {//通过 Person 的 id 获取到 Person,包括这个 Person 关联的 IdenCard 对象public Person getPersonById(Integer id);
}

8.创建PersonMapper.xml文件

1.写xml用association的第一种方式

<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.PersonMapper"><!-- 实现 getPersonById [方式 1] --><!-- 定义一个 resultMap 来映射返回的结果 --><resultMap type="Person" id="personResultMap"><!-- id: 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能, 通常指定主键property="id" 表示 person 对象的哪个属性代表主键column="id" 表示对应的表的字段 --><id property="id" column="id"/><result property="name" column="name"/><!-- association: 一个复杂类型的关联 -->
<!--     javaType:返回的java的类型
--><association property="card" javaType="com.sn.entity.IdenCard"><!-- 将关联的 card 对象哪些属性放入到这个 resultMap --><result property="id" column="id"/><result property="card_sn" column="card_sn"/></association></resultMap><select id="getPersonById" parameterType="Integer" resultMap="personResultMap">select * from person , idencard WHERE person.id=#{id}AND person.card_id = idencard.id;</select>
</mapper>

2.用xml中association的第二种方式 

<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.PersonMapper"><!-- 实现 getPersonById [方式 2] --><!-- 定义一个 resultMap 来映射返回的结果 --><resultMap type="Person" id="personResultMap2"><!-- id: 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能, 通常指定主键property="id" 表示 person 对象的哪个属性代表主键column="id" 表示对应的表的字段 --><id property="id" column="id"/><result property="name" column="name"/><!-- association: 一个复杂类型的关联 --><association property="card" column="card_id"select="com.sn.mapper.IdenCardMapper.getIdenCardById"/></resultMap><select id="getPersonById2" parameterType="Integer" resultMap="personResultMap2">
select * from person where id = #{id}</select>
</mapper>

测试结果:

查询的结果:: 

总结 :

上面上述案例就是:多表查询,就是当我们查询一个表的一条记录的时候,其中的某个属性是另外一个表的主键(也就是可以标识一条记录的属性)。也就是外键约束!

当我们实现一对一的映射的时候,想要使返回的结果如上图所示,就必须用resultMap进行结果的映射。

 当我们在XML文件进行方法的实现的时候,mybatis框架会根据方法中的结果映射,返回出你所想要的结果。这里的一对一的映射,就是平常大学老师教的方法,同时这里涉及到了级联查询(也就是所说的多表查询)


2.通过注解的方式来实现下面的 1 1 的映射关系,实现级联查询

 1.创建IdenCardMapperAnnotaion

package com.sn.mapper;import com.sn.entity.IdenCard;
import org.apache.ibatis.annotations.Select;/*** @author sn*/
public interface IdenCardMapperAnnotaion {//根据 id 获取到身份证
//这个方法不需要返回任何级联对象@Select("SELECT * FROM idencard WHERE id=#{id}")public IdenCard getIdenCardById(Integer id);
}

2.创建 PersonMapperAnnotatio

package com.sn.mapper;import com.sn.entity.Person;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;/*** @author sn*/
public interface PersonMapperAnnotation {//通过 Person 的 id 获取到 Person,包括这个 Person 关联的 IdenCard 对象
//想:你到底返回什么结果,然后你想办法给他
/*
* private Integer id;
private String name;
private IdenCard card;
*/@Select("select * from person WHERE id=#{id}")@Results({@Result(id = true, property = "id", column = "id"), @Result(property = "name", column = "name"), @Result(property = "card", column = "card_id", one = @One(select ="com.sn.mapper.IdenCardMapperAnnotaion.getIdenCardById"))})public Person getPersonById(Integer id);
}

查询的结果:: 

 

运行的结果也和之前是一样的,用动态代理的方式 

总结:

1. 表是否设置外键 , MyBatis 进行对象 / 级联映射没有影响
也就是无论是否有外键约束,在mybatis中依然可以查到相关联的身份证号所带来的消息。

 

2.  去掉 person 表的外键 , 进行测试 , 依然可以获取相应的级联对象
通过注解的方法和XML的方法其实本质是一致的,更推荐使用XML的形式来进行解耦!
另外还有一点column中的属性值是你查询过后的表的字段名,如果你的SQL语句给表的字段取别名了那么这个column是别名的名字

二. 映射关系多对一

1. 项目中多对 1 的关系是一个基本的映射关系 , 多对 1, 也可以理解成是 1 对多 .
User --- Pet : 一个用户可以养多只宠物
Dep ---Emp : 一个部门可以有多个员工
目的就是:
通过 User 可以查询到对应的 Pet, 反过
来,通过 Pet 也可以级联查询到对应的 User 信息 .实现双向的多对一的映射。

1.通过xml文件实现映射的多对一关系

1. 创建 mybatis_user 和 mybatis_pet 表

CREATE TABLE mybatis_user
(id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL DEFAULT '' )CHARSET=utf8 ;

CREATE TABLE mybatis_pet
(id INT PRIMARY KEY AUTO_INCREMENT,
nickname VARCHAR(32) NOT NULL DEFAULT '',
user_id INT ,
FOREIGN KEY (user_id) REFERENCES mybatis_user(id)
)CHARSET=utf8 ;

INSERT INTO mybatis_user
VALUES(NULL,'宋江'),(NULL,'张飞');


INSERT INTO mybatis_pet
VALUES(1,'黑背',1),(2,'小哈',1);


INSERT INTO mybatis_pet
VALUES(3,'波斯猫',2),(4,'贵妃猫',2);

SELECT * FROM mybatis_user;
SELECT * FROM mybatis_pet;

 2.创建User类

package com.sn.entity;import java.util.List;/*** @author sn*/
public class User {private Integer id;private String name;//一个用户可以对应多个宠物private List<Pet> pets;public User() {}public User(Integer id, String name, List<Pet> pets) {this.id = id;this.name = name;this.pets = pets;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<Pet> getPets() {return pets;}public void setPets(List<Pet> pets) {this.pets = pets;}
}

3创建Pet类

package com.sn.entity;/*** @author sn*/
public class Pet {private Integer id;private String nickname;//一个宠物只能对应一个主人 Userprivate User user;public Pet() {}public Pet(Integer id, String nickname, User user) {this.id = id;this.nickname = nickname;this.user = user;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname = nickname;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}@Overridepublic String toString() {return "Pet{" +"id=" + id +", nickname='" + nickname + '\'' +'}';}
}

 

3. 创建 PetMapper.java 和 UserMapper.java
public interface PetMapper {
// 通过 User id 来获取 pet 对象,可能有多个,因此使用 List 接收
public List < Pet > getPetByUserId ( Integer userId);
// 通过 pet id 获取 Pet 对象
public Pet getPetById ( Integer id);
}
public interface UserMapper {
// 通过 id 获取 User 对象
public User getUserById ( Integer id);
}

 

4. 创建 UserMapper.xml 

 <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.UserMapper">
<resultMap type="com.sn.entity.Pet" id="PetResultMap"><id property="id" column="id"/><result property="nickname" column="nickname"/><association property="user" column="user_id" select="com.sn.mapper.PetMapper.getUserById"></association>
</resultMap>
<!-- :
1. user_id=#{userId} userId 就是调用 getPetByUserId 传入的用户 id
2. userId 名称,由程序员来确定,比如你写成 id,uId 等都可以-->
<select id="getPetByUserId" parameterType="Integer" resultMap="PetResultMap">select * from mybatis_pet where user_id=#{userId}
</select>
<select id="getPetById" parameterType="Integer" resultMap="PetResultMap">select * from mybatis_pet where id=#{id}
</select>
</mapper>

 

5. 创建 PetMapper.xm
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.PetMapper"><!-- collection : 一对多关联查询, 表示一个用户可能对应多个 pet 对象ofType: 集合中元素对象的类型 --><resultMap type="com.sn.entity.User" id="UserResultMap"><id property="id" column="id"/><result property="name" column="name"/><!-- column="id" 就是当前 User 表的主键字段名,通过这个 user 的 id,去查询对应的 pet 有哪些 --><collection property="pets" ofType="com.sn.entity.Pet" column="id"select="com.sn.mapper.UserMapper.getPetByUserId"></collection></resultMap><select id="getUserById" parameterType="Integer" resultMap="UserResultMap">select * from mybatis_user where id=#{id};</select>
</mapper>

  那么问题来了?有人会问那如果这个方法的参数有多个怎么办呢?

: 在数据库库中表和表的联系可以通过外键约束进行,也就是一个表的非主属性,对应的是另外一个表的主键,而表的主键只有一个(主键就是可以唯一标识一条记录的属性字段)。所以为啥只有一个参数了。

2.通过注解的方式来实现下面的 多对一 的映射关系,实现级联查询

1.UserMapperAnnotation 接口

package com.sn.mapper;import com.sn.entity.User;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;/*** @author sn*/
public interface UserMapperAnnotation {//通过 user 的 id 号,返回该用户的方法@Select("select * from mybatis_user where id=#{id}")@Results({@Result(id=true,property="id",column="id"),@Result(property="name",column="name"),@Result(property="pets",column="id",many=@Many(select="com.sn.mapper.PetMapperAnnotation.getPetByUserId"))})public User getUserById(Integer id);
}

 

 2.PetMapperAnnotation接口

package com.sn.mapper;import com.sn.entity.Pet;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;import java.util.List;/*** @author sn*/
public interface PetMapperAnnotation {//通过 User 的 id 来获取 pet 对象,可能有多个,因此使用 List 接收@Select("select * from mybatis_pet where user_id=#{userId}")@Results({@Result(id = true, property = "id", column = "id"),@Result(property = "nickname", column = "nickname")})public List<Pet> getPetByUserId(Integer userId);
//通过 pet 的 id 获取 Pet 对象@Select("select id AS tnId,nickname AS tnNickname, user_id AS tnUser_id from mybatis_pet where id=#{id}")@Results({@Result(id = true, property = "id", column = "tnId"),@Result(property = "nickname", column = "tnNickname"),@Result(property = "user", column = "tnUser_id",one = @One(select ="com.sn.mapper.UserMapperAnnotation.getUserById"))})public Pet getPetById(Integer id);
}

XML与注解的形式本质都是以XML的形式进行的,只不过注解对XML进行可一个封装。

映射关系就是你在查询一个表的时候,其中的某个属性对应另外一个表的一条记录,或者多条记录。比如你在查询教师表中的某个教师的信息,同时根据这个教师的工号,你可以查到这个教师所教的班级,以及班级的学生等信息。

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

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

相关文章

【Elasticsearch系列十五】强大特性

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

MapReduce基本原理

目录 整体执行流程​ Map端执行流程 Reduce端执行流程 Shuffle执行流程 整体执行流程 八部曲 读取数据--> 定义map --> 分区 --> 排序 --> 规约 --> 分组 --> 定义reduce --> 输出数据 首先将文件进行切片&#xff08;block&#xff09;处理&#xff…

EsDA,一站式嵌入式软件

EsDA是一套面向工业智能物联领域的嵌入式系统设计自动化工具集&#xff0c;包含实时操作系统AWorksLP、低代码开发平台AWStudio、资源管理平台AXPI、跨平台GUI引擎AWTK和云服务平台ZWS&#xff0c;旨在提高嵌入式软件开发的效率、性能和可扩展性。 EsDA全称是嵌入式系统设计自动…

司南 OpenCompass 九月大语言模型评测榜单启动召集,欢迎新合作厂商申请评测

主要概览 司南 OpenCompass 大语言模型官方自建榜单&#xff08;9 月榜&#xff09;评测拟定于 10 月上旬发布&#xff0c;现诚挚邀请新加入的合作方参与评测。本次评测围绕强化能力维度&#xff0c;全面覆盖语言、推理、知识、代码、数学、指令跟随、智能体等七大关键领域&am…

ThreaLocal

1.概述 ThreadLoca称线程局部变量&#xff0c;用于在线程中保存数据&#xff0c;保存的数据仅属于当前线程(即对其他线程而言&#xff0c;该变量是当前线程独有的变量) threadLocal利用Thread中的ThreadLocalMap来进行数据存储 2.常用方法 存储数据至当前线程ThreadLocalMap中…

Unity引擎绘制多边形属性图

大家好&#xff0c;我是阿赵   在制作游戏的时候&#xff0c;经常会遇到需要绘制多边形属性图的需求&#xff0c;比如这种效果&#xff1a; 可以根据需要的属性的数量变化多边形的边数&#xff0c;然后每一个顶点从中心点开始到多边形的顶点的长度代表了该属性的强度&#xf…

谈对象第二弹: C++类和对象(中)

文章目录 一、类的默认成员函数二、构造函数三、析构函数四、拷贝构造函数五、运算符重载5.1运算符重载5.2赋值运算符重载5.3实现日期类<<、>>重载检查、获取天数关系运算符重载算数、赋值运算符重载Date.hDate.cpp 六、取地址运算符重载6.1const成员函数6.2取地址…

docker部署excalidraw画图工具

0&#xff09;效果 0.1&#xff09;实时协作 0.2&#xff09;导出格式 1&#xff09;docker安装 docker脚本 bash <(curl -sSL https://cdn.jsdelivr.net/gh/SuperManito/LinuxMirrorsmain/DockerInstallation.sh)docker-compose脚本 curl -L "https://github.com/…

Dynaform 5.9.4简体中文版百度云下载(含教程)

如大家所了解的&#xff0c;Dynaform是一种基于有限元分析&#xff08;FEA&#xff09;技术的计算机辅助工程&#xff08;CAE&#xff09;软件&#xff0c;常常用于模拟和优化各种工业应用中的结构和流体问题。 目前常用的版本为Dynaform 5.9.4&#xff0c;可以模拟机械结构、…

第314题|参考!如何做到【一题多解】|武忠祥老师每日一题

解析&#xff1a; 画出图像&#xff1a; 观察选项可知&#xff1a;选项A和选项B是相反选项&#xff0c;因此答案只能在AB当中。 因此本题我们只需要算出和的大小即可。 方法一&#xff1a;直接相减然后判断结果的正负。 分析题目给的条件&#xff1a;f(x)单调减少&#xff0…

肥胖成因:饮食之外,消耗吸收慢是关键因素

肥胖问题一直被现代社会所关注&#xff0c;不可否认&#xff0c;饮食是影响胖瘦的重要因素之一。高热量、高油脂的食物摄入过多&#xff0c;也确实会导致热量油脂过剩&#xff0c;堆积储存进身体内进而养肥身体。可在正常情况中&#xff0c;就算是消耗吸收率一般的人&#xff0…

828华为云征文 | 在Huawei Cloud EulerOS系统中安装Docker的详细步骤与常见问题解决

前言 Docker是一种轻量级的容器技术&#xff0c;广泛用于应用程序的开发、部署和运维。在华为云的欧拉&#xff08;Huawei Cloud EulerOS&#xff09;系统上安装和运行Docker&#xff0c;虽然与CentOS有相似之处&#xff0c;但在具体实现过程中&#xff0c;可能会遇到一些系统…

进程状态的优先级

1.进程的状态&#xff08;所有系统&#xff09; 因为是对于所有系统的&#xff0c;所以描述会很抽象。 补充知识&#xff1a; 并行和并发 并行&#xff1a;多个进程再多个cpu下分别同时运行并发&#xff1a;多个进程在一个cpu下采取进程切换的方式&#xff0c;在一段时间内&…

echarts实现地图下钻并解决海南群岛显示缩略图

一、准备工作 1、echarts版本&#xff1a; ^5.5.1 2、去掉海南数据的json文件 二、获取删除过后的json文件 1、DataV.GeoAtlas地理小工具系列 (aliyun.com) 在网站输入这个复制的&#xff0c;新建一个json文件粘贴进去。 接下来需要删除两个地方&#xff0c;不要删错&…

左手研发,右手销量,比亚迪舍弃了什么?

早买早享受&#xff0c;晚买享折扣&#xff0c;是近一年来汽车消费市场的真实写照。 A级家轿价格下探至6、7万元&#xff1b;曾经20万起步的主流B级车&#xff0c;如今只要12万元就能入手&#xff1b;即使是BBA等豪华品牌&#xff0c;也开始降价促销换销量。买车更便宜了&…

【最优化】一维最优化方法:华罗庚黄金分割优选法

一、意义 华先生提倡用数学实际服务国民经济发展&#xff0c;受限于当时计算能力有限&#xff0c;华先生总结经验&#xff0c;提出黄金分割优选法&#xff0c;能够用最少的试验次数找出最优解。 二、主要内容 ①应用范围&#xff1a;一维单峰函数 ②算法步骤&#xff1a; ③详…

Qt/C++ TCP调试助手V1.1 新增图像传输与接收功能(附发布版下载链接)

发布版本链接 通过百度网盘分享的文件&#xff1a;TCP调试助手V1.zip&#xff08;含客户端与服务器&#xff09; 链接&#xff1a;https://pan.baidu.com/s/14LTRPChPhYdwp_s6KeyBiA?pwdcedu 提取码&#xff1a;cedu 基于Qt/C实现了一款功能丰富的TCP服务器与客户端调试助手…

【已解决】华为AR100-S路由器 恢复出厂后,找不到5G wifi的设置

前两帖讨论了华为AR100-S路由器&#xff1a; 一是用电脑浏览器访问web管理界面报错的解决&#xff0c;详情点这里&#xff01; https://blog.csdn.net/weixin_62598385/article/details/142215136 再就是如何回复出厂&#xff0c;也即如何复位&#xff0c; 详情点这里&#xff…

微服务保护详细笔记(一):雪崩问题--Sentinel

目录 1.雪崩问题 1.1.雪崩问题产生原因&#xff1a; 1.2.雪崩问题解决方案 1.2.1.请求限流 1.1.2.线程隔离 1.1.3.服务熔断 1.3.微服务保护技术对比 1.4.Sentinel 1.4.1.介绍与安装 1.4.2.微服务整合 1.雪崩问题 1.1.雪崩问题产生原因&#xff1a; 比如查询购物车的…

SEO之页面优化(二—描述标签)

初创企业搭建网站的朋友看1号文章&#xff1b;想学习云计算&#xff0c;怎么入门看2号文章谢谢支持&#xff1a; 1、我给不会敲代码又想搭建网站的人建议 2、“新手上云”能够为你开启探索云世界的第一步 博客&#xff1a;阿幸SEO~探索搜索排名之道 2、描述标签 描述标签是H…