Mybatis学习笔记10 高级映射及延迟加载

2023-09-20 16:10:42

Mybatis学习笔记9 动态SQL_biubiubiu0706的博客-CSDN博客

无论简单映射(前面所学的单表和对象之间的映射关系)还是高级映射

说到底都是java对象和数据库表记录之间的映射关系

准备数据库表:一个班级对应多个学生.班级表:t_class   学生表:s_stu(自增) 

新建模块

项目整体结构

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>mybatis-09</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>
        <!--mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <!--logback依赖-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>
        <!--junit依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

SqlSessionUtil

package example.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

/**
 * @author hrui
 * @date 2023/9/8 14:55
 */
public class SqlSessionUtil {

    //工具类的构造方法一般都是私有化
    //方法都是静态的
    //为了防止new对象,构造方法私有化
    private SqlSessionUtil(){

    }
    private static SqlSessionFactory sqlSessionFactory;

    //类加载时候执行
    //SqlSessionUtil工具类在被加载的时候,解析mybatis-config1.xml.创建sqlSessionFactory对象
    static{
        try {
            //SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
            //下面这么写的原因是SqlSessionFactoryBuilder就是为了创建sqlSessionFactory而来的,使用完后,就不需要,都不需要创建个局部变量
            //一个sqlSessionFactory对应一个数据库
            sqlSessionFactory= new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config1.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //全局的 服务器级别的,一个服务器当中定义一个即可
    private static ThreadLocal<SqlSession> local=new ThreadLocal<>();

    //获取会话对象 返回会话对象
    public static SqlSession openSession(){
        SqlSession sqlSession=local.get();
        if(sqlSession==null){
            sqlSession = sqlSessionFactory.openSession();
            local.set(sqlSession);
        }

        return sqlSession;
    }

    //提供一个关闭的方法
    public static void close(SqlSession sqlSession){
        if(sqlSession!=null){
            //因为核心配置文件中配置POOLED  这里关闭是交还给连接池
            sqlSession.close();
            //注意移除SqlSession对象和当前线程的绑定关系
            //因为Tomcat服务器支持线程池 比如说t1线程用完了,close交还给连接池了,这个sqlSession属于不可用的状态,你没有remove出去 如果t2线程拿到了,那么这个sqlSession不可用
            local.remove();
        }
    }
}

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!--定义⽇志⽂件的存储地址-->
    <property name="LOG_HOME" value="D:/home"/>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示⽇期,%thread表示线程名,%-5level:级别从左显示5
           个字符宽度%msg:⽇志消息,%n是换⾏符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天⽣成⽇志⽂件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--⽇志⽂件输出的⽂件名-->
            <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--⽇志⽂件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示⽇期,%thread表示线程名,%-5level:级别从左显示5
           个字符宽度%msg:⽇志消息,%n是换⾏符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logge
                r{50} - %msg%n</pattern>
        </encoder>
        <!--⽇志⽂件最⼤的⼤⼩-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>100MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <!--mybatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>
    <!-- ⽇志输出级别,logback⽇志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!--转驼峰-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!--指定实体类包别名-->
    <typeAliases>
        <package name="example.pojo"/><!--这样写指定包,resultType可以类名并且不区分大小写 比如cAr CAR CaR caR-->
<!--        <typeAlias type="pojo.Car" alias="aaa"></typeAlias>-->
<!--        <typeAlias type="pojo.Log" alias="bbb"></typeAlias>-->
        <!--alias别名可以省却,默认大小写类名-->
<!--        <typeAlias type="pojo.Log"></typeAlias>-->
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="1"/>
                <property name="username" value="1"/>
                <property name="password" value="1!"/>
                <property name="poolMaximumActiveConnections" value="10"/><!--最大连接数-->

                <property name="poolMaximumIdleConnections" value="5"/><!--最大空闲连接-->
                <property name="poolMaximumCheckoutTime" value="20000"/><!--检出时间毫秒 默认即20秒-->
            </dataSource>
        </environment>
<!--        <environment id="development2">-->
<!--            <transactionManager type="JDBC"/>-->
<!--            <dataSource type="UNPOOLED">-->
<!--                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>-->
<!--                <property name="url" value="jdbc:mysql://localhost:3306/mybatis3"/>-->
<!--                <property name="username" value="root"/>-->
<!--                <property name="password" value="123456"/>-->
<!--            </dataSource>-->
<!--        </environment>-->
    </environments>
    <!--resource属性会自动从类的根路径下开始查找资源.-->
    <!--
    1.<package name="包名"> 标签用于自动扫描指定包下的映射文件,要求映射文件名和接口名保持一致,并且映射文件(.xml)和接口需要在同一个包中,否则会报错。
    2.<mapper class=""> 标签的class属性用于注册映射文件,同样要求映射文件名和接口名保持一致,并且映射文件(.xml)和接口需要在同一个包中,否则会报错。
    3.<mapper resource="org/xx/demo/mapper/xx.xml"/> 标签用于注册映射文件,与上述两种方式不同,这种方式不要求映射文件名和接口名一致。这里是通过命名空间(namespace)和mapper接口对应的,命名空间要与接口的全限定名保持一致。
    4.<mapper url="file:///d:/StuMapper.xml" />是绝对路径加载映射文件的,而且 .xml 文件的名称并不需要和接口名称相同。通过命名空间指定和接口关系
    -->
    <!--告诉mybatis去哪里找mapper文件-->
    <mappers>
        <mapper resource="mapper/StuMapper.xml"/>
        <mapper resource="mapper/ClazzMapper.xml"/>
    </mappers>
</configuration>

在Student暂时没有把cid作为属性,一会用特殊处理方式  不需要将cid这个关系字段放进去

 

Clazz

两个接口对应两个映射.xml

多对一映射实体    多个学生对应一个班级  反过来就是一个班级对应多个学生

所谓ORM    O(JVM里的对象内存)     R(数据库表记录)     M(Mapping映射关系)

创建多对一实体类   Student修改以下  把Clazz放进去

把两张表的数据映射为对象

多对一  

3种方式

第⼀种⽅式:⼀条SQL语句,级联属性映射。
第⼆种⽅式:⼀条SQL语句,用association标签。
第三种⽅式:两条SQL语句,分步查询。(这种⽅式常⽤:优点⼀是可复⽤。优点⼆是⽀持懒加
载。)
第⼀种⽅式:⼀条SQL语句,级联属性映射。
第⼆种⽅式:⼀条SQL语句,用association标签。
第三种⽅式:两条SQL语句,分步查询。(这种⽅式常⽤:优点⼀是可复⽤。优点⼆是⽀持懒加
载。)
这种方式   第一:就是用学生id查出学生信息  第二:用学生关联的班级id去查班级信息
上面这种方式有利于复用.都是独立的一个功能,其他地方也可以用

关于延迟加载(默认不开启,只针对当前SQL语句)

也就是说,第二步的SQL需不需要执行,看你用不用(如何理解看下面)

可以通过配置mybatis核心配置文件来控制是否开启全局懒加载,如果配置了全局懒加载  那么这里的可以去掉不写

如果配置了  那么  

fetchType="lazy"可以不写

实际开发中,此种情况都应该开启全局懒加载(局延迟加载)--->针对此种写法的sql

如果说,开启了全局延迟加载,但是我的这两句SQL不想用延迟加载,那么添加

fetchType="eager"

实际开发一般配全局延迟加载   如果你的分步SQL有特殊需要  可以fetchType="eager"

输出student的话,就是说已经用了

下面演示   

一对多关系

一个班级有多个学生     班级为主表    把学生放到班级类中    多个学生对象List<Student>

1对多

1为主表  即Clazz

在Clazz表中新增字段List<Student> stus;

1对多的映射实现通常两种方式:

第⼀种⽅式:collection
第⼆种⽅式:分步查询
第⼀种⽅式:collection
第⼆种⽅式:分步查询
首先查班级信息          然后该班级的学生信息    
关于1对1关系
关于多对多.......
   
更多推荐

【超实用】2023年,学生上班族如何简单快速,低成本的搭建一个博客网站

文章目录前言实操环节香港虚拟机购买博客搭建ssl证书配置备份设置总结前言因为工作和生活的需要,我一直有博客的搭建需求。我将总结下来,为读者提供参考。起初,我采用的是香港云虚拟主机,这种虚拟机极其便宜(一个月几块钱),域名免备案。这非常好,我用了一段时间发现,香港虚拟机的内地访问速度比较慢,并且服务商可能过一两年就会跑路

紫光展锐5G芯T820 解锁全新应用场景,让机器人更智能

数字经济的持续发展正推动机器人产业成为风口赛道。工信部数据显示,2023年上半年,我国工业机器人产量达22.2万套,同比增长5.4%;服务机器人产量为353万套,同比增长9.6%。作为国内商用服务机器人领先企业,云迹科技近日在“云迹UP服务平台全球首发”发布会上表示,机器人正迎来3.0时代,从原来单纯只能执行单一功能的

计算机网络 套接字函数 | socket、bind、listen、accept、connect

欢迎关注博主Mindtechnist或加入【LinuxC/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。socket、bind、listen、accept、co

【AI视野·今日Robot 机器人论文速览 第三十六期】Tue, 19 Sep 2023

AI视野·今日CS.Robotics机器人学论文速览Tue,19Sep2023(showingfirst100of112entries)Totally112papers👉上期速览✈更多精彩请移步主页DailyRoboticsPapersGeneralIn-HandObjectRotationwithVisionand

基于SpringBoot+Vue的宠物领养饲养交流管理平台设计与实现

前言💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗👇🏻精彩专栏推荐订阅👇🏻2023-2024年最值得选的微信小程序毕业设计选题大全:100个热门选

游戏初步——发牌程序(控制台版)以及一些扩展(python)

目录题目要求:初始代码:实际上,如果pocker直接存储扑克牌,而不是扑克牌的编号,则程序更加简单,但是pocker列表创建书写麻烦一些。修改后代码如下:算法描述或实验步骤最终代码:代码详解:技能1:查找对子技能2:查找数量最多的花色技能3:查找最长连续顺子题目要求:请完成《4.6游戏初步——发牌程序(控制台版)》,并

人脸图像数据增强

为什么要做数据增强在计算机视觉相关任务中,数据增强(DataAugmentation)是一种常用的技术,用于扩展训练数据集的多样性。它包括对原始图像进行一系列随机或有规律的变换,以生成新的训练样本。数据增强的主要目的是增加模型的泛化能力、提高模型的鲁棒性,并减轻过拟合的风险。以下是进行数据增强的几个重要原因:增加数据样

学习笔记|外部中断|INT0|中断列表|STC32G单片机视频开发教程(冲哥)|第十五集:中断系统和外部中断

文章目录1.中断和中断系统1.1什么是中断?1.2什么是中断系统1.3中断系统的优点1.4中断系统包含哪些中断源1.5.中断次序2.什么是外部中断3.外部中断的用法4.外部中断的用法新的测试场景完整代码总结课后练习:上节课我们学完了GPIO的矩阵按键,已经把这个GPIO的一个外设全都已经学完了今天开始我们要学习这个单片

COVID疫苗加强针来袭,是否该接种?

Sience子刊新研究揭示:COVID-19病毒影响人体线粒体功能,或成治疗新途径NatureMedicine:脑雾、记忆和注意力不集中可能是新冠感染引发的血栓导致的Nature揭秘--为什么有些白人感染新冠病毒后不会生病SARS-CoV-2重复感染将为常态整个北半球,公卫人员正在紧锣密鼓地推进秋季COVID-19疫苗

NLP进阶,使用TextRNN和TextRNN_ATT实现文本分类

TextRNNTextRNN仅仅是将WordEmbedding后,输入到双向LSTM中,然后对最后一位的输出输入到全连接层中,在对其进行softmax分类即可,模型如下图:代码:classRNN(nn.Module):def__init__(self,vocab_size,embedding_dim,hidden_di

SpringMVC学习|Servlet回顾、理解SpringMVC小demo、SpringMVC原理

Servlet回顾创一个空的maven父工程,导入相关依赖,测试的、spring的、servlet的、jsp以及jstl标签的。创建一个空的maven子项目,并添加web支持为了保险起见,在子项目中添加servlet和jsp的依赖编写一个Servlet类,实现HttpServlet接口获取前端参数,以及重定向,这里为了

热文推荐