【Mybatis篇】Mybatis的关联映射详细代码带练 (多对多查询、Mybatis缓存机制)

 

      🧸安清h:个人主页

   🎥个人专栏:【计算机网络】,【Mybatis篇】

🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。


 

目录

 

🎯一.关联映射概述

🚦简述

🚦三种Java对象关联映射关系

 🎯二.多对多查询

 🚦数据表准备

🚦POJO类准备

🚦映射文件

🚦核心配置文件

🚦创建接口类

🚦创建Util类

🚦创建测试类

🎯Mybatis缓存机制

🚦简述

🚦一级缓存

✨数据表准备

✨POJO类准备

✨映射文件

✨创建接口类

✨创建log4j.properties文件 

✨创建测试类 

🚦二级缓存


🎯一.关联映射概述


🚦简述

        关联映射是数据处理和编程中的一个重要概念,尤其在数据库和面向对象编程中应用广泛。它主要处理实体之间的关系,无论是将这种关系映射到数据库表之间,还是在面向对象编程中处理类之间的关系。实体通常指的是具体的事物,如用户、订单、产品等,在数据库中通常表示为表,而表中的每一行代表一个实体。

        关联映射的核心在于处理实体之间的关系,这种关系可以是简单的对应关系,也可以是更复杂的如一对一、一对多或多对多的关系。例如,一个用户可以有多个订单,但一个订单只属于一个用户,这就是典型的一对多关系。在数据库中,这种关系需要通过外键来建立连接,确保数据的完整性和准确性。

        在面向对象编程中,关联映射则处理类之间的关系。类是对象的模板或蓝图,定义了对象的属性和行为。当两个类需要建立关联关系时,通常通过属性引用来实现。这种关联是有方向性的,也就是说,一个类可能引用另一个类的实例,但不一定被另一个类的实例所引用。

🚦三种Java对象关联映射关系

1.一对一(1:1)关联映射:

  1. 在这种关系中,一个对象与另一个对象有且仅有一个关联。
  2. 例如,一个用户(User)对象可能与一个个人资料(Profile)对象关联,每个用户只有一个个人资料,每个个人资料也只属于一个用户。
  3. 在数据库中,这通常通过在两个表之间共享一个主键或者使用外键来实现。
  4. 在Java类中,可以通过在一个类中定义另一个类的实例作为私有成员来表示。

2.一对多(1:N)关联映射:

  1. 这种关系表示一个对象可以与多个对象关联,而每个对象只能与一个对象关联。
  2. 例如,一个部门(Department)对象可以有多个员工(Employee)对象,但每个员工只能属于一个部门。
  3. 在数据库中,通常是通过在“多”的一方的表中包含“一”的一方的表的主键作为外键来实现的。
  4. 在Java类中,这通常是通过在“一”的一方的类中定义一个集合(如List或Set)来表示,而在“多”的一方的类中定义一个指向“一”的一方的引用。

3.多对多(M:N)关联映射:

  1. 在这种关系中,两个对象可以相互关联多个对象。
  2. 例如,学生(Student)和课程(Course)之间的关系,一个学生可以选多个课程,一个课程也可以被多个学生选择。
  3. 在数据库中,这通常需要一个中间表(或称为连接表),该表包含两个关联表的主键。
  4. 在Java类中,这通常是通过在两个类中各自定义一个集合来表示,每个集合包含对方类的实例。

Java对象描述数据之间的关系示意图如下:

 🎯二.多对多查询

 🚦数据表准备

在数据库mybatis中创建三个表,分别为product产品表,ordersitem关联表,orders订单表,并向三个表中插入数据,具体代码如下:

#创建orders表
create table orders(id int primary key auto_increment,number varchar(50) not null ,user_id int not null,foreign key (user_id ) references user(id)
);#插入数据
insert into orders values (1,'10001',1);
insert into orders values (2,'10002',2);
insert into orders values (3,'10003',3);#创建product表
create table product(id int primary key auto_increment,name varchar(100),price DOUBLE
);#插入数据
insert into product values (1,'红楼梦',59);
insert into product values (2,'三国演义',53);
insert into product values (3,'水浒传',62);#创建ordersitem表
create table ordersitem(id int primary key auto_increment,orders_id int,product_id int,foreign key (orders_id) references orders(id),foreign key (product_id) references product(id)
);#插入数据
insert into ordersitem values (1,1,1);
insert into ordersitem values (2,1,3);
insert into ordersitem values (3,3,3);

🚦POJO类准备

在包com.haust.pojo中创建类Product和类Orders,在类Product中会有一个私有成员变量productList,它的类型是List<Orders>,意味着 productList 是一个可以存储多个 Product 对象的列表。类Orders同样如此。

类Product具体代码如下:

public class Product {private int id;private String name;private Double price;private List<Orders> orders;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}public List<Orders> getOrders() {return orders;}public void setOrders(List<Orders> orders) {this.orders = orders;}@Overridepublic String toString() {return "Product{" +"id=" + id +", name='" + name + '\'' +", price=" + price +", orders=" + orders +'}';}
}

类Orders具体代码如下:

public class Orders {private Integer id;private String number;private List<Product> productList;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}public List<Product> getProductList() {return productList;}public void setProductList(List<Product> productList) {this.productList = productList;}@Overridepublic String toString() {return "Orders{" +"id=" + id +", number='" + number + '\'' +", productList=" + productList +'}';}
}

🚦映射文件

在resources中的mapper包中创建两个映射文件,分别是ProductMapper.xml和OrdersMapper.xml。

OrdersMapper.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="com.haust.mapper.OrdersMapper"><select id="findOrdersWithProduct" parameterType="Integer"resultMap="OrdersWithProductResult">select * from orders where id=#{id}</select><resultMap id="OrdersWithProductResult" type="com.haust.pojo.Orders"><id property="id" column="id"/><result property="number" column="number"/><collection property="productList" column="id" ofType="com.haust.pojo.Product"select="com.haust.mapper.ProductMapper.findProductById"></collection></resultMap>
</mapper>

ProductMapper.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="com.haust.mapper.ProductMapper"><select id="findProductById" parameterType="Integer" resultType="com.haust.pojo.Product">select * from product where id in(select product_id from ordersitem where orders_id=#{id})</select>
</mapper>

🚦核心配置文件

在mybatis-config.xml文件中添加如下代码:

<mappers><mapper resource="mapper/OrdersMapper.xml"/><mapper resource="mapper/ProductMapper.xml"/></mappers>

🚦创建接口类

在com.haust.mapper包中分别创建接口类ProductMapper和OrdersMapper。

ProductMapper具体代码如下:

public interface ProductMapper {List<Product> findProductById(Product product);
}

 OrdersMapper具体代码如下:

public interface OrdersMapper {List<Orders> findOrdersWithProduct(Orders orders);
}

🚦创建Util类

在com.haust.util包中创建类MybatisUtil,具体代码如下:

public class MybatisUtil {private static SqlSessionFactory sqlSessionFactory=null;static {try {Reader reader= Resources.getResourceAsReader("mybatis-config.xml");sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);} catch (IOException e) {throw new RuntimeException(e);}}public static SqlSession getSession(){return sqlSessionFactory.openSession();}
}

🚦创建测试类

最后在包com.haust.test中创建测试类MybatisTest,并在其中编写测试方法testFindById,具体代码如下:

 @Testpublic void testFindById(){SqlSession sqlSession=MybatisUtil.getSession();OrdersMapper ordersMapper=sqlSession.getMapper(OrdersMapper.class);Orders orders=new Orders();orders.setId(1);List<Orders> list=ordersMapper.findOrdersWithProduct(orders);for(Orders o:list){System.out.println(o);}sqlSession.close();}

🎯Mybatis缓存机制

🚦简述

MyBatis的缓存机制包括一级缓存和二级缓存。

        一级缓存(Local Cache)是基于SqlSession的,它默认是开启的,并且不能关闭。一级缓存的作用域是同一个SqlSession,在同一个SqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库查询的数据写到缓存(内存),第二次会从缓存中获取数据而不进行数据库查询,从而提高了查询效率。一级缓存的生命周期很短,当SqlSession调用close()方法时,一级缓存将不可用。如果SqlSession调用了clearCache()方法,会清空一级缓存中的数据,但是SqlSession对象还可以使用。此外,SqlSession中执行了任何一个update(修改)、delete(删除)、insert(新增)操作后,一级缓存也会被清空。

        二级缓存(Global Cache)是跨SqlSession的,它的作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递的参数也相同时,第一次执行完毕会将数据库中查询到的数据写到缓存(内存),第二次会直接从缓存中获取,从而提高了查询效率。二级缓存需要手动配置开启,配置文件中使用<cache>元素进行配置,并在需要使用二级缓存的映射文件中添加<cache-ref>元素引用全局的缓存。二级缓存可以配置多种参数,如缓存回收策略、刷新间隔、引用数目、只读等。二级缓存默认是不开启的,需要在MyBatis配置文件中设置开启。

🚦一级缓存

在数据表中多次查询同一信息,第一次查询时,程序会将查询结果写入Mybatis一级缓存,在第二次查询时,Mybatis直接从一级缓存中读取,不再访问数据库进行查询。在执行增删改任意操作时,Mybatis会清空缓存中的内容以防止程序误读。

✨数据表准备

create table book(id int primary key auto_increment,bookName varchar(100),price DOUBLE,author varchar(100)
);insert into  book values (1,'红楼梦',57,'曹雪芹');
insert into book values (2,'西游记',48,'吴承恩');
insert into book values (3,'三国演义',67,'罗贯中');

✨POJO类准备

public class Book implements Serializable {private Integer id;private String bookName;private Double price;private String author;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getBookName() {return bookName;}public void setBookName(String bookName) {this.bookName = bookName;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}@Overridepublic String toString() {return "Book{" +"id=" + id +", bookName='" + bookName + '\'' +", price=" + price +", author='" + author + '\'' +'}';}
}

✨映射文件

<?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.haust.mapper.BookMapper"><select id="findBookById" parameterType="Integer" resultType="com.haust.pojo.Book">select * from book where id=#{id}</select></mapper>

✨创建接口类

public interface BookMapper {List<Book> findBookById(Book book);
}

✨创建log4j.properties文件 

#全局日志配置
log4j.rootLogger=DEBUG,Console
#控制台输出配置
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#日志输出级别
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

✨创建测试类 

    @Testpublic void testFindBook(){SqlSession sqlSession= MybatisUtil.getSession();BookMapper bookMapper=sqlSession.getMapper(BookMapper.class);Book book=new Book();book.setId(1);List<Book> list=bookMapper.findBookById(book);for(Book b:list){System.out.println(b);}Book book2=new Book();book2.setId(1);List<Book> list2=bookMapper.findBookById(book);for(Book b2:list2){System.out.println(b2);}sqlSession.close();}

🚦二级缓存

任意的增删改会导致二级缓存失效,二级缓存需要手动开启,首先是需要在mybatis-config.xml中通过<settings>元素开启二级缓存全局配置:

<settings><setting name="cacheEnabled" value="true"/></settings>

其次是 通过Mybatis映射文件中的<cache>元素来完成,载<mapper>元素下添加如下代码:

<cache></cache>

为了验证上述配置,在测试类中添加测试方法testFindById2,具体代码如下:

  @Testpublic void testFindById2(){SqlSession sqlSession1=MybatisUtil.getSession();SqlSession sqlSession2=MybatisUtil.getSession();Book book1=sqlSession1.selectOne("com.haust.mapper.BookMapper.findBookById",1);System.out.println(book1.toString());sqlSession1.close();Book book2=sqlSession2.selectOne("com.haust.mapper.BookMapper.findBookById",1);System.out.println(book2.toString());sqlSession1.close();}

以上就是今天要讲的内容了,到此为止,Mybatis关联映射部分已经更完,如果您对我的文章感兴趣的话,可以订阅我的专栏【Mybatis篇】,在接下来的文章中会写到Mybatis的注解开发,非常感谢您的阅读,如果这篇文章对您有帮助,那将是我的荣幸。我们下期再见啦🧸!

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

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

相关文章

RTSP协议讲解

1.RTSP协议 rtsp&#xff0c;英文全称 Real Time Streaming Protocol&#xff0c;RFC2326&#xff0c;实时流传输协议&#xff0c;是 TCP/IP 协议体系中的一个应用层协议。 RTSP 交互流程 1&#xff09;OPTIONS C--->S 客户端向服务器端发现 OPTIONS&#xff0c;请求可用…

html中的文本标签(含标签的实现案例)

目录 1.标题标签 2.标题标签的align属性 3.段落标签 4.水平线标签hr 5.换行标签br 6.文本样式标签font ​编辑7.文本格式化标签 8.文本语义标签 1&#xff09;时间time标签 2&#xff09;文本高亮Mark标签 3&#xff09;cite标签 9.特殊字符标签 10.图像标签img 附录&#xff…

基于微信小程序的旅游拼团系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

gitee公钥设置、创建库及使用

简介 一、如何安装git 使用gitee&#xff0c;需要先安装git工具。 工具网站地址&#xff1a;https://git-scm.com/downloads 安装完成后&#xff0c;在terminal命令行输入git --version可以查看到git的版本。 二、登录gitee 我们先在 gitee上注册账号并登录。gitee官网&#x…

震动传感器介绍及实战

目录 前言 震动传感器 1.震动传感器配图 2.震动传感器原理图 3.震动传感器使用 1-震动传感器的意义 2-震动传感器的应用场景 3- SW-18010P震动传感器使用方法 震动传感器控制灯 操作 增加延时 使用SPC-ISP生成演示函数 总结 前言 我们上节已经简单了解了LED的使用…

二、变量与基本类型

变量与基本类型 变量定义声明和使用 基本类型数字类型介绍运算算术运算符位运算符赋值运算符运算符优先级 布尔类型字符类型字符串类型 变量 定义 变量&#xff0c;指值可以变的量。变量以非数字的符号来表达&#xff0c;一般用拉丁字母。变量的用处在于能一般化描述指令的方式…

MongoDB集群模式详解及应用实战

目录 本节课内容&#xff1a; 集群搭建 1.创建3个目录&#xff1a; 2.编辑配置文件 ​编辑 3.启动&#xff1a; 4.看看&#xff1a; 5.另外&#xff0c;两个如上1&#xff0c;2&#xff0c;3步骤操作 &#xff0c;但是日志目录&#xff0c;端口什么的需要改一下即可。 …

10以内数的分解

// 10以内数的分解.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 //#include <iostream> using namespace std; int main(int argc, char* argv[]){for (int i 2; i < 10; i){for (int j 1; j < i; j){printf("%d%d%d ",j…

操作系统学习笔记---文件管理

文件系统基础 概念 文件&#xff1a;以计算机硬盘为载体的存储在计算机上的信息集合 文件的属性 文件具有一定的属性&#xff0c;系统不同&#xff0c;属性也会有所不同&#xff0c;但通第都包括如下属性&#xff1a;名称、标识符、类型、位置、大小、保护、时间、日期和用…

vue3+vite@4+ts+elementplus创建项目详解

1、第一步创建项目cnpm init vite4 2、设置vue3.2局域网可访问配置&#xff1a; 找到项目路径下的package.json目录下找到script对象下面添加一下代码&#xff1a; "serve": "vite --host 0.0.0.0" 启动项目命令不在是dev而是&#xff1a;cnpm run serve 3…

《深度学习》OpenCV 摄像头OCR 过程及案例解析

目录 一、摄像头OCR 1、含义 2、一般操作步骤 1&#xff09;安装OpenCV库 2&#xff09;设置摄像头 3&#xff09;图像采集 4&#xff09;图像预处理 5&#xff09;文本识别 6&#xff09;文本处理 7&#xff09;结果显示 二、案例实现 1、定义展示图像函数 2、定…

深入理解 JavaScript 事件循环机制:单线程中的异步处理核心

深入理解 JavaScript 事件循环机制&#xff1a;单线程中的异步处理核心 JavaScript 是一门单线程的编程语言&#xff0c;也就是说它在同一时间只能执行一个任务。然而&#xff0c;现代 Web 应用经常需要处理大量的异步操作&#xff0c;如用户输入、网络请求、定时器等。为了确…

《迁移学习》—— 将 ResNet18 模型迁移到食物分类项目中

文章目录 一、迁移学习的简单介绍1.迁移学习是什么&#xff1f;2.迁移学习的步骤 二、数据集介绍三、代码实现1. 步骤2.所用到方法介绍的文章链接3. 完整代码 一、迁移学习的简单介绍 1.迁移学习是什么&#xff1f; 迁移学习是指利用已经训练好的模型&#xff0c;在新的任务上…

鸿蒙开发(NEXT/API 12)【状态查询与订阅】手机侧应用开发

注意 该接口的调用需要在开发者联盟申请设备基础信息权限与穿戴用户状态权限&#xff0c;穿戴用户状态权限还需获得用户授权。 实时查询穿戴设备可用空间、电量状态。订阅穿戴设备连接状态、低电量告警、用户心率告警。查询和订阅穿戴设备充电状态、佩戴状态、设备模式。 使…

初识Django

前言: 各位观众老爷们好&#xff0c;最近几个月都没怎么更新&#xff0c;主要是最近的事情太多了&#xff0c;我也在继续学习Django框架&#xff0c;之前还参加了一些比赛&#xff0c;现在我会开始持续更新Django的学习&#xff0c;这个过程会比较久&#xff0c;我会把我学习的…

MySQL--三大范式(超详解)

目录 一、前言二、三大范式2.1概念2.2第一范式&#xff08;1NF&#xff09;2.3第二范式&#xff08;2NF&#xff09;2.3第三范式&#xff08;3NF&#xff09; 一、前言 欢迎大家来到权权的博客~欢迎大家对我的博客进行指导&#xff0c;有什么不对的地方&#xff0c;我会及时改进…

嘴尚绝卤味:健康美味的双重奏

在当今快节奏的生活中&#xff0c;人们对美食的追求不再仅仅停留于味蕾的满足&#xff0c;更加注重食物的健康与营养。在这一背景下&#xff0c;"嘴尚绝卤味"以其独特的健康理念与精湛的制作工艺&#xff0c;成为了市场上备受瞩目的卤味品牌。本文将从"嘴尚绝卤…

Kotlin基本知识

Kotlin是一种现代的静态类型编程语言&#xff0c;由JetBrains公司在2010年推出&#xff0c;并被Google在2019年宣布为Android开发的首选语言。 超过 50% 的专业 Android 开发者使用 Kotlin 作为主要语言&#xff0c;而只有 30% 使用 Java 作为主要语言。 70% 以 Kotlin 为主要语…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑光伏不确定性的配电网谐波监测优化配置方法 》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

Azure DevOps Server:不能指派新增的用户

Contents 1. 概述2. 解决方案 1. 概述 近期和微软Azure DevOps项目组解决了一个“无法指派开发人员”的问题&#xff0c;在此分享给大家。问题描述&#xff1a; 在一个数据量比较大的Azure DevOps Server的部署环境中&#xff0c;用户发现将新用户的AD域账户添加到Azure DevOps…