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

news2024/10/5 20:31:20

 

      🧸安清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;
    }

    @Override
    public 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;
    }

    @Override
    public 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 mapper
        PUBLIC "-//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 mapper
        PUBLIC "-//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,具体代码如下:

 @Test
    public 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;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", bookName='" + bookName + '\'' +
                ", price=" + price +
                ", author='" + author + '\'' +
                '}';
    }
}

✨映射文件

<?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">
<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

✨创建测试类 

    @Test
    public 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,具体代码如下:

  @Test
    public 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.coloradmin.cn/o/2190476.html

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

相关文章

【BUG】P-tuningv2微调ChatGLM2-6B时所踩的坑

0.前言 P-tuning v2的实验在网上一抓一大把&#xff0c;这里就说一下我在微调过程中遇到的有些bug&#xff0c;踩过的一些坑&#xff0c;在网上找了很久都没有一些好的解决方案&#xff0c;在这里记录一下。 1.下载预训练模型 在官方给出的教程中&#xff0c;并不需要预先将模…

【springboot】简易模块化开发项目整合Swagger2

接上一项目【springboot】简易模块化开发项目整合MyBatis-plus&#xff0c;进行拓展项目 1.新建模块 右键项目→New→Module&#xff0c;新建一个模块 父项目选择fast-demo&#xff0c;命名为fast-demo-config&#xff0c;用于存放所有配置项 添加后&#xff0c;项目结构如图…

X3U·可编程控制器的定位控制

FX3U可编程控制器的定位控制进行说明。 一、概要 FX3U可编程控制器可以向伺服电机、步进电机等输出脉冲信号&#xff0c;从而进行定位控制。 脉冲频率高的时候&#xff0c;电机转得快:脉冲数多的时候&#xff0c;电机转得多。用脉冲频率、脉冲数来设定定位对象…

Linux基本命令及vim应用实训练习

Linux基本命令及vim应用实训练习 1. 2. 3. 4. 5. 使用man cp找出

4 思科模拟器的介绍和使用

4 思科模拟器的介绍和使用 思科的IOS给我们提供了三大模式 设备开机后&#xff0c;进入的模式是【用户模式】 Router表示设备的名称 “>”表示用户模式 在用户模式输入"?" 可列出在用户模式可以使用的命令 第二种模式是特权模式,输入enable进入特权模式&…

RNN经典案例——构建人名分类器

RNN经典案例——人名分类器 一、数据处理1.1 去掉语言中的重音标记1.2 读取数据1.3 构建人名类别与人名对应关系字典1.4 将人名转换为对应的onehot张量 二、构建RNN模型2.1 构建传统RNN模型2.2 构建LSTM模型2.3 构建GRU模型 三、构建训练函数并进行训练3.1 从输出结果中获得指定…

字符和ACSII编码

1.字符和ASCII编码 C语言中char类型&#xff0c;专门用来创建字符变量&#xff0c;字符放在单引号中 char ch a ASCII码表 c官网&#xff0c;最全de c官网链接 数字字符0~9对应ASCII码十进制48~57 字符 大写字母A~Z对应ASCII码十进制65~90 字符 小写字母a~z对应ASCII码…

EtherCAT 转 EtherNet/IP, EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关

EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关https://item.taobao.com/item.htm?ftt&id822721028899协议转换通信网关 EtherCAT 转 EtherNet/IP GW系列型号 MS-GW12 概述 MS-GW12 是 EtherCAT 和 EtherNet/IP 协议转换网关&#xff0c;为用户提供两…

突发!Meta重磅发布Movie Gen入局视频生成赛道!

引言 Meta于2024年10月4日首次推出 Meta Movie Gen&#xff0c;号称是迄今为止最先进的媒体基础模型。Movie Gen 由 Meta 的 AI 研究团队开发&#xff0c;在一系列功能上获取最先进的效果&#xff0c;包括&#xff1a;文生视频、创建个性化视频、精准的视频编辑和音频创作。 …

递归--C语言

1 递归定义 函数自己调用自己的过程&#xff0c;称为递归。 2 递归的必要条件 1.必须要有终止条件。达到条件就停止递归&#xff0c;退出函数。2.每次调用自己都要越来越接近这个终止条件。 因此写函数的时候&#xff0c;也分两部分 第一部分&#xff1a;写终止条件&#x…

点击按钮提示气泡信息(Toast)

演示效果&#xff1a; 目录结构&#xff1a; activity_main.xml(布局文件)代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http:…

【第三版 系统集成项目管理工程师】第15章 组织保障

持续更新。。。。。。。。。。。。。。。 【第三版】第十五章 组织保障 15.1信息和文档管理15.1.1 信息和文档1.信息系统信息-P5462.信息系统文档-P546 15.1.2 信息(文档)管理规则和方法1.信息(文档)编制规范-P5472.信息(文档)定级保护-P5483.信息(文档)配置管理-P549练习 15.…

38 文件包含(标准库头文件、自定义头文件)、相对路径与绝对路径、条件编译(#if、#ifdef、#if define、#ifndef)

目录 1 文件包含 1.1 #include 指令 1.2 包含标准库头文件 1.3 包含自定义头文件 1.3.1 使用相对路径 1.3.2 使用绝对路径 2 条件编译 2.1 #if … #endif 2.1.1 语法格式 2.1.2 功能说明 2.1.3 流程分析 2.1.4 案例演示&#xff1a;#if 0 ... #endif 2.1.5 案例演…

关于懒惰学习与渴求学习的一份介绍

在这篇文章中&#xff0c;我将介绍些懒惰学习与渴求学习的算法例子&#xff0c;会介绍其概念、优缺点以及其python的运用。 一、渴求学习 1.1概念 渴求学习&#xff08;Eager Learning&#xff09;是指在训练阶段构建出复杂的模型&#xff0c;然后在预测阶段运用这个构建出的…

分布式锁--redission 最佳实践!

我们知道如果我们的项目服务不只是一个实例的时候&#xff0c;单体锁就不再适用&#xff0c;而我们自己去用redis实现分布式锁的话&#xff0c;会有比如锁误删、超时释放、锁的重入、失败重试、Redis主从一致性等等一系列的问题需要自己解决。 当然&#xff0c;上述问题并非无…

3dsMax合并FBX的时候相同的节点会被合并(重命名解决),3Ds MAX创建空物体(虚拟对象或者点)

3dsMax合并FBX的时候相同的节点会被合并 3dsamax的文档&#xff0c;但是并没有说FBX的合并如何处理 https://help.autodesk.com/view/3DSMAX/2024/CHS/?guidGUID-98146EB8-436F-4954-8682-C57D4E53262A模型节点信息&#xff0c;yase&#xff0c;Points&#xff0c;Mesh 都是点…

【优选算法】(第二十一篇)

目录 外观数列(medium) 题目解析 讲解算法原理 编写代码 数⻘蛙&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 外观数列(medium) 题目解析 1.题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 2.题目描述 给定⼀个正整数n&#xff0…

openpnp - 坐标文件中的元件0角度如果和编带规定的角度不一样,需要调整贴片任务中的元件旋转角度

文章目录 openpnp - 坐标文件中的元件0角度如果和编带规定的角度不一样&#xff0c;需要调整贴片任务中的元件旋转角度笔记查看自己图纸中的封装的0角度方法贴片任务的角度值范围编带规定的0角度根据编带规定的元件0角度来调整贴片的元件旋转角度如果是托盘飞达备注备注END ope…

电脑失声,一招搞定

早已习惯了Edge浏览器的“大声朗读”功能&#xff0c;今天值班&#xff0c;值班室用的两台电脑只配有耳机&#xff0c;没有音箱&#xff0c;顿时感觉不适。 先找了一个带功放的老音箱&#xff0c;发现少了电箱到功放的音频线。 一顿搜索&#xff0c;在找到音频线的同时&#…

2024年计算机视觉与艺术研讨会(CVA 2024)

目录 基本信息 大会简介 征稿主题 会议议程 参会方式 基本信息 大会官网&#xff1a;www.icadi.net&#xff08;点击了解参会投稿等信息&#xff09; 大会时间&#xff1a;2024年11月29-12月1日 大会地点&#xff1a;中国-天津 大会简介 2024年计算机视觉与艺术国际学术…