[Java]MyBatis轻松拿下

news2024/9/30 1:34:51

介绍

在业务开发过程中, 都是使用java程序完成数据库的操作, 目前最主流的技术就是MyBatis

MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。

  1. 官网: https://mybatis.org/mybatis-3/zh/index.html
  2. mybatis是Apache的一个开源项目iBatis, 2010年迁移到了google code 并改名为Mybatis
  3. 2013年11月迁移到Github

快速入门

1.使用流程

1.1准备工作

  1. 创建springboot工程, 勾选
  • Mybatis Framework (Mybatis依赖)
  • MySQL Druver (MySQL驱动依赖)
  • 清理原始工程

  1. 准备实体类
  • 用于封装查询出来的数据
  • 实体类的属性名与表中的字段名一一对应。
  • 实体类的属性类型建议使用包装类型
  • 生成get/set方法
  • 生成有参构造器和无参构造器
  • 重写toString()方法
  1. 准备数据库表

1.2配置Mybatis

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/数据库名字
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234

1.3编写SQL语句

  1. 创建Mapper包, 定义持久层接口XxxMapper,
  2. 使用@Mapper注解标识接口;
  • 作用: 把接口交给Mybatis管理
  • 在运行时, mybatis会自动生成该接口的实现类对象, 并且把该对象交给IOC容器管理
  • 作用: 简化数据库的操作
  1. 定义抽象方法, 书写SQL语句
  • 通过注解执行SQL语句

1.4启动测试

@SpringBootTest //springboot整合单元测试的注解
class Day03MybatisApplicationTests {

    // 注入Mapper接口的实现类对象
    @Autowired
    private UserMapper userMapper;

    @Test
    public void testListUser() {
        // 调用实现类对象的方法完成数据库操作
        List<User> userList = userMapper.list();
        userList.stream().forEach(user -> {
            System.out.println(user);
        });
    }

}

2.配置提示

打开语法提示: 默认在mybatis中编写sql语句是不识别的, 可以做一些配置

关联数据库: 在IDEA和数据库默认没有建立连接, 所以不能提示表信息, 需要在idea中配置Mysql数据库信息

3.JDBC

JDBC是java语言操作关系型数据库的一套API

  1. sun公司官方定义的一套操作所有关系型数据可的规范, 即接口
  2. 各个数据库厂商去实现这套接口, 提供数据库驱动jar包
  3. 我们使用这套接口(JDBC)编程, 真正执行的代码是驱动jar包中的实现类

JDBC操作数据库存在的问题

  1. 注册驱动这块的代码存在硬编码现象
  2. 封装数据库数据的代码非常繁琐, 需要一条一条的封装
  3. 每次操作数据库都要创建和释放资源, 性能降低

  1. 在mybatis中, 通过配置的方式连接数据库
  2. 通过注解执行sql语句, 就可以完成数据库操作以及数据封装
  3. 通过数据库连接池, 管理数据库连接对象, 避免频繁创建和释放资源
  4. 使用mybatis操作数据库, 只需要配置连接信息, 编写mapper接口, 非常高效

4.数据库连接池

数据库连接池是个容器, 负责分配 管理数据库连接对象.

标准接口

  1. DetaSource 是官方(sun)提供的数据库连接池接口, 供第三方公司实现
  2. 如果想要开发连接池驱动, 就必须实现该接口
  3. 该接口的作用就是获取数据库连接对象
  4. 核心方法: Connection getConnection() thows SQLException;
  5. 常见产品

  1. Hikari(追光者)是springboot默认使用的连接池技术
  2. Druid(德鲁伊)是阿里巴巴开源的连接池技术, 功能强大, 性能优秀

切换连接池

  1. 德鲁伊官网:

  2. 切换到Druid连接池, 只需要引入德鲁伊连接池依赖就可以了

  1. 切换的效果

5.lombok

lombok的作用就是简化实体类的定义, 提高开发效率

  1. Lombok是一个实用的java类库,
  2. 通过注解的形式, 可以自动生成构造器, getter/setter. equals, hashcide, toString等方法,
  3. 还可以自动生成日志变量

引入

// 无需指定版本
// 因为lombok已经集成到springboot父工程中, 统一管理版本
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
</dependency>

注解

插件

  1. lombok在编译时, 会自动生成对应的java代码, 使用lombok时, 还需要安装插件
  2. ieda自带该插件, 较老版本的ieda可能需要手动安装

注解

通过Mybatis提供的注解, 完成数据库的增删改查操作

1.删除数据

@mapper // 把接口交给myBatis管理
public interface EmpMapper {
    //指定sql语句: 根据id删除数据
    @Delete("delete from emp where id = #{id}")
    public void delete(Integer id);
}
@SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisCrudApplicationTests {
    // 注入empMapper对象
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testDelete () {
        // 执行对象的删除方法
        empMapper.delete(17);
    }
}
  1. 删除操作会返回一个int类型的数值, 表示删除成功的个数, 需要的时候获取
  2. mybatis提供了参数占位符 #{}, 用于读取方法传递的参数

2.参数占位符

1.开启日志输出

在application.prpperties文件中开启日志输出功能, 我们就能在控制台看到mybatis执行的slq语句

#指定mybatis输出日志的位置(输出控制台)
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
3.演示sql注入

SQL注入是通过操作输入的数据来修改系统的sql语句, 达到对服务器进行攻击的方法

执行jar包

// 打开cmd窗口, 定位到文件所在目录
java -jar 文件名

访问项目

// 正常访问
select count(*) from emp where username = 'zhangwuji' and posseord = '123456';
// 登录失败
select count(*) from emp where username = 'zhangwuji' and posseord = '11111';
// sql攻击
select count(*) from emp where username = 'aaass' and posseord = '' or '1' = '1';
3.预编译sql

在mybatis中, 使用 #{ ... } 占位的SQL语句, 生成的就是预编译SQL

  1. 当SQL真正执行时, 会自动将 #{} 内的值替换到 ? 号位置, 形成完整的语句
  2. 参数的传递, 都使用#{...}, 安全可靠

预编译sql拥有更好的执行性能(缓存机制) 和 更好的安全防护(sql注入)

  1. 拼接sql: 每次执行的sql语句都是不同的, 所以无法命中缓存中的sql语句
  2. 动态sql: 每次执行的sql语句都是相同的, 可以命中缓存中的sql语句, 在执行阶段拼接具体的值
4.拼接SQL

在mybatis中, 使用 #${ ... } 占位的SQL语句, 生成的就是拼接SQL

  1. 直接将参数拼接在SQL语句中, 一般很少使用
  2. 如果对表名, 列表进行动态设置时使用

4.新增数据

@mapper // 把接口交给myBatis管理
public interface EmpMapper {
    // 开启主键返回, 并指定将主键值赋值给实体类的id属性
    @Options(useGeneratedKeys = true, keyProperty = "id")
     //指定sql语句: 新增员工
    @Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
            "values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
    public void insert(Emp emp);
}
@SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisCrudApplicationTests {
    // 注入empMapper对象
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testDelete () {
        // 构建员工对象
        Emp emp = new Enm();
        // 为对象添加数据
        emp.setUsername("Tom");
        emp.setName("汤姆");
        emp.setGender((short) 1);
        emp.setJob((short) 1);
        emp.setEntrydate(LocalDate.of(2000,1,1));
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setDeptId(1);
        
        // 执行对象的新增方法
        empMapper.insert(emp);
        // 如果开启了主键返回, 就可以拿到新增数据的id主键值
        System.out.printIn(emp.getId());
    }
}
  1. 主键返回: 新增操作默认不会返回主键的值, 如果需要主键值时, 通过添加注解开启
  2. 开启主键返回后, 新增操作完成, 可以通过实体类, 拿到新增数据的id主键值

5.修改数据

@mapper // 把接口交给myBatis管理
public interface EmpMapper {
     //指定sql语句: 更新员工
     @Update("update emp set username = #{username},name=#{name},gender = #{gender},image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id =#{id};")
     public void update(Emp emp);
}
@SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisCrudApplicationTests {
    // 注入empMapper对象
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testDelete () {
        // 构建员工对象
        Emp emp = new Enm();
        // 为对象添加数据
        emp.setUsername("Tom");
        emp.setId(18);
        emp.setName("汤姆");
        emp.setGender((short) 1);
        emp.setJob((short) 1);
        emp.setEntrydate(LocalDate.of(2000,1,1));
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setDeptId(1);
        
        // 执行对象的更新方法
        empMapper.update(emp);
    }
}

6.数据封装

实体类属性名 和 数据库表的字段名一致, Mybatis会自动封装

实体类属性名 和 数据库表的字段名不一致, 不能自动封装

  1. 通过查询语句查到数据, 把数据封装到实体中, 返回给前端
  2. 由于实体类采用驼峰命名法, 数据库中采用下划线分割, 会导致有些数据无法自动封装

1.起别名

在SQL语句中, 给不一样的字段名设置一个别名, 别名和实体类的属性名一致, 就可以正确封装数据

2.手动结果映射

通过@Results 和 @Result 注解, 手动对映射结果进行调整, 以正确的封装数据

3.开启驼峰命名转换

让Mybatis自动把 下划线的字段名 转成 驼峰命名风格, 以完成封装数据

#开启mubatis驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true

7.查询数据

@mapper // 把接口交给myBatis管理
public interface EmpMapper {
    //指定sql语句:  根据id查询员工
    @Select("select * from emp where id= #{id}")
    public Emp getById(Integer id);
}
@mapper // 把接口交给myBatis管理
public interface EmpMapper {
    //指定sql语句:  根据条件查询员工
    @Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +
            "entrydate between #{begin} and #{end} order by update_time desc;")
    public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
}
@SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisCrudApplicationTests {
    // 注入empMapper对象
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testGetById () { 
        // 执行对象的查询方法
        Emp emp = empMapper.getById(1);
        System.out.printIn(emp);
    }

      @Test
    public void testList () { 
        // 执行对象的条件查询方法
        List<Emp> list = empMapper.list("张", (short) 1, LocalDate.of(2010,1,1), LocalDate.of(2020,1,1));
        System.out.printIn(list);
    }
}
  1. #{}不能在引号内使用, ${}可以在引号内使用, 但是不推荐使用
  2. 建议使用mysql提供的 concat() 拼接函数, 用于拼接字符串
  3. concat('hello', 'Mysql' ,'!!!') 执行结果是 'helloMysql!!!'

8.版本差异

在早期或者单独使用mybatis时, 需要使用 @Param()注解 声明形参, 才能在 #{} 中使用数据, 原因是spinrgboot2.x版本 中引用了一个插件, 可以在编码后记住形参的名字, 有名字才能正确的访问数据

XML

使用mybatis的注解, 主要用来完成简单的增删改查, 如果是复杂的sql, 建议使用 xml 文件来映射sql语句

1,创建xml文件

XML映射文件的名称与Mapper接口名称一致,并且XML文件和Mapper接口放置在相同包下(同包同名)

<?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="待定">
    
</mapper>

2,设置namespace属性

XML映射文件的namespace属性为Mapper接口全限定名一致

复制接口全类名:

<mapper namespace="com.itheima.mapper.EmpMapper">
</mapper>

3.编写sql, 设置id属性

XML映射文件中, sql语句的id 与Mapper文件中的方法名一致, 并保持返回类型一致

<mapper namespace="com.itheima.mapper.EmpMapper">

  // resultType: 单条记录所封装的类型(指定返回值的类型)
  // id="xx":  id与mapper文件的方法名一致
   <select id="list" resultType="com.itheima.pojo.Emp">
       select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and
         entrydate between #{begin} and #{end} order by update_time desc;
   </select>

</mapper>

4.插件

MybatisX是一款基于IDEA的快速开发Mabatis的插件, 为效率而生

生成XML文件中的sql标签

  1. alt +enter -> Generate statement -> 自动生成SQL语句

  1. ctrl +alt + L : 格式化sql语句

动态SQL

随着条件变化而变化的SQL语句称为动态sql

if标签

用于判断条件是否成立, 使用test属性进行条件判断, 如果条件为true, 则拼接SQL,

需求: 根据条件查询员工, 筛选字段有值, 则作为条件, 没有值则忽略

<select id="list" resultType="com.itheima.pojo.Emp">
  select * from emp
  where 
    <if test="name != null">
        name like concat('%', #{name}, '%')
    </if>
    <if test="gender != null">
        and gender = #{gender}
    </if>
    <if test="begin != null and end != null">
        and entrydate between #{begin} and #{end}
    </if>
   order by update_time desc
</select>
  1. 以上代码通过 if标签 实现了条件的动态拼接
  2. 但是代码存在问题, 不传name, 只根据gender查询, sql语句中就会多出一个 and关键字
  3. 所以在书写动态sql时, 会使用where标签 替换 where关键字

where元素只会在 子元素有内容 的情况下才插入where子句, 而且会自动去除子句 多余的AND 或 OR

<select id="list" resultType="com.itheima.pojo.Emp">
    select * from emp
    <where>
        <if test="name != null">
            name like concat('%',#{name},'%')
        </if>
         <if test="gender != null">
             and gender = #{gender}
         </if>
         <if test="begin != null and end != null">
             and entrydate between #{begin} and #{end}
         </if>
     </where>
     order by update_time desc
</select>

动态的在行首插入 SET 关键字, 并会删除多余的逗号, 用在update语句中

需求: 动态更新员工数据, 如果更新时传递有值,则更新该字段, 否则不更新

<update id="update">
    update emp
    <set>
        <if test="username != null">username = #{username},</if>
        <if test="name != null">name = #{name},</if>
        <if test="gender != null">gender = #{gemder},</if>
        <if test="job != null">job = #{job},</if>
        <if test="updateTime != null">update_time = #{updateTime}</if>
     </set>
     where id = #{id}
</select>
  1. 如果不使用set标签替换set关键字, 代码就会有问题
  2. 比如只传入username字段, 后面的字段不传, sql语句中就会多出一个逗号
  3. 所以在动态更新数据时, 会使用set标签替换set关键字

foreach标签

循环遍历, 主要用在批量操作中

// 批量删除员工
public void deleteByIds(List<Integer> ids);
// 批量删除员工(18,19,20)
<delete id="deleteById">
    delete from emp where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
         #{id}
    </foreach>
</delete>

sql标签

封装重复性的SQL语句

<mapper namespace="com.itheima.mapper.EmpMapper">
    // 定义可重用的sql片段
    <sql id="唯一名称">
      select id,username,password,name,gender,image,job,entrydate,dept_id,create_time,update_time
      from emp
    </sql>

   <select id="list" resultType="com.itheima.pojo.Emp">
      // 通过refid属性, 引入sql片段
      <include refid = "唯一名称"  />
      where 
        <if test="name != null">
            name like concat('%', #{name}, '%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
       order by update_time desc
    </select>
</mapper>

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

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

相关文章

Day00_场景题

文章目录 资料项目经历技能清单自我介绍QPS和TPS?如何设计一个排行榜的功能?如何解决大文件上传问题延时任务处理场景如何设计一个秒杀系统?分布式幂等性如何设计?如果你的系统的QPS 突然提升10倍你会怎么设计?如何从零搭建 10 万级QPS 大流量、高并发优惠券系统?高 QPS,…

OpenCV绘图函数(9)填充多边形函数fillPoly()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 填充一个或多个多边形轮廓所包围的区域。 函数 cv::fillPoly 填充由若干个多边形轮廓所包围的区域。该函数可以填充复杂的区域&#xff0c;例如带…

【大模型】GPT系列模型基础

前言&#xff1a;GPT整体上与transformer结构相似&#xff0c;但只用了decoder部分。 目录 1. GPT2. GPT23. GPT34. 知识补充4.1 下游任务实现方式4.2 sparse attention 1. GPT 预训练&#xff1a;无监督&#xff0c;根据前k个词预测下一个词的概率。微调&#xff1a; 有监督&a…

AI嵌入式人工智能开发 --- 【1】初始RKNPU

目录 一、NPU的由来 二、RKNPU介绍 三、RKNPU单核框架 3.1 AHB/AXI 接口 3.2 卷积神经网络加速单元&#xff08;CNA&#xff09; 3.3 数据处理单元&#xff08;Data Processing Unit&#xff0c;DPU&#xff09; 3.4 平面处理单元&#xff08;Planar Processing Unit&a…

#驱动开发

内核模块 字符设备驱动 中断、内核定时器 裸机开发和驱动开发的区别&#xff1f; 裸机开发 驱动开发&#xff08;基于内核&#xff09; 相同点 都能够控制硬件&#xff08;本质&#xff1a;操作寄存器&#xff09; 不同点 用C语言给对应的地址里面写值 按照一定的框架格式…

【DSP+FPGA】基于DSP+FPGA XC7K325T与TMS320C6678的通用信号处理平台

DSP FPGA 协同处理架构板载 1 个TMS320C6678 多核DSP处理节点板载 1 片 XC7K325T FPGA处理节点板载 1 个FMC 接口板载4路SFP光纤接口FPGA 与 DSP 之间采用高速Rapid IO互联 基于FPGA与DSP协同处理架构的通用高性能实时信号处理平台&#xff0c;该平台采用1片TI的KeyStone系列多…

CSS3 文本效果(text-shadow,box-shadow,white-space等)

一 text-shadow text-shadow 属性是 CSS3 中用于为文本添加阴影效果的工具。它可以增强文本的可读性和视觉吸引力&#xff0c;提供丰富的视觉效果 1 语法 text-shadow: offset-x offset-y blur-radius color;offset-x&#xff1a;阴影相对于文本的水平偏移量。可以是正值&am…

c/c++: function和procedure的区别

https://www.cs.nthu.edu.tw/~ychung/slides/CSC4180/Alfred%20V.%20Aho,%20Monica%20S.%20Lam,%20Ravi%20Sethi,%20Jeffrey%20D.%20Ullman-Compilers%20-%20Principles,%20Techniques,%20and%20Tools-Pearson_Addison%20Wesley%20(2006).pdf 函数与过程的区别&#xff0c;一个…

AI语音识别神器Openai Whisper对中文的支持如何?

文章目录 前言一、资料准备二、Whisper环境搭建第一步&#xff1a;安装whisper第二步&#xff1a;安装ffmpeg 三、Whisper测试总结其他相关 前言 语音识别一直以来都是人工智能领域中一个不容忽视的技术&#xff0c;随着大模型时代的到来&#xff0c;这项技术也发生了质的变化…

解决MAC电脑SVN Android studio不能提交.so文件相关

目录 前言 确认问题原因 修改 SVN 配置文件 验证配置是否生效 其他注意事项 总结 前言 在使用 macOS 进行开发时&#xff0c;可能会遇到通过 SVN 在 Android Studio 中无法提交 .so 文件的问题。这通常是由于 SVN 配置文件中的 global-ignores 设置导致的&#xff0c;…

比特币牛市将至背后

作者&#xff1a;Arthur Hayes 编译&#xff1a;Liam 「此处所表达的任何观点均为作者个人意见&#xff0c;不应作为投资决策依据&#xff0c;也不应被视为参与投资交易的推荐或建议。」 我打破常规&#xff0c;前往南半球滑雪两周&#xff0c;为北半球的暑假画上圆满的句号。我…

03. SpringBoot 项目创建

接下来我们将要完成一个基础的 Springboot 项目的创建&#xff0c;并且将项目上传到 Gitee 1. 查看官网&#xff0c;选择版本 学习任何一门技术&#xff0c;一定要学会从官网了解一手信息&#xff0c;无论是哪个博主的博客都是有时效性的&#xff0c;我们要掌握这样的习惯&…

Runtime Asset Database 运行时资产数据库

运行时资产数据库是一个库,旨在简化Unity应用程序中运行时保存和加载子系统的实现。此库复制并扩展了Unity编辑器中常见的预制件、预制件变体和资源的概念,使其在运行时比以往任何时候都更容易管理和操纵游戏资源,并在运行时动态实现与Unity编辑器类似的工作流。 Unity开发人…

晟鑫商会与家盛资本携手合作,共创金融科技新篇章

在数字化浪潮的推动下,金融科技正成为全球经济发展的新引擎。近日,晟鑫商会与家盛资本宣布达成战略合作伙伴关系,旨在通过创新合作,共同开拓市场新机遇,促进双方在数字经济领域的深入发展。两家机构的联合预示着在金融科技领域将开启一段新的旅程。 晟鑫商会,作为互联网商业合作…

做好价格监测这些点要注意

品牌在进行数据监测时&#xff0c;首要关注点在于数据本身的准确率与覆盖率&#xff0c;而在价格监测方面亦是如此。品牌需高度关注电商价格监测系统输出的价格、促销信息、销量等数据。一旦促销信息出现不准确的情况&#xff0c;到手价必然会受到影响&#xff0c;进而对后端治…

USB PHY——ULPI

ULPI协议的全称是UTMI Low Pin Interface。从名字上就可以看出ULPI是UTMI的Low Pin版本。 ULPI是在UTMI的基础上封装了一层。 ULPI需要读写寄存器&#xff0c;而UTMI只需直接拉高或拉低信号线。 从这张图可以看出 ULPI 是在 UTMI level3 再往上一层 外设参考设计

ssm面向企事业单位的项目申报小程序论文源码调试讲解

2 系统实现的技术支持 2.1微信开发者工具 在传统web浏览器中&#xff0c;在加载htm15页面时先加载视图层的html和css&#xff0c;后加载逻辑层的java script&#xff0c;然后返回数据并在浏览器中展示页面。而微信开发者工具的系统层是基于Native System的&#xff0c;视图层和…

COMP9315-week2-lecture1

COMP9315 19T2 Week 2 Lecture 1_哔哩哔哩_bilibili C:\python\COMP9315-master\19T2\Lectures\weel02.pdf COMP9315 24T1 - Course Notes (unsw.edu.au) 前面三分之一时间讲week1的练习题&#xff0c;是一个存储过程 COMP9315-master\19T2\Lecture Exercises\week01\ex05\…

AcWing859. Kruskal算法求最小生成树

一定要看这个链接的讲解视频&#xff1a;强烈推荐&#xff01;&#xff01;&#xff01;【图-最小生成树-Prim(普里姆)算法和Kruskal(克鲁斯卡尔)算法】 文章目录 1.题目2.Kruskal基本思想&#xff1a;3.逐行解释代码&#xff1a; 1.题目 2.Kruskal基本思想&#xff1a; Krus…

sql-labs46-50通关攻略

第46关 一.查询数据库 http://172.16.1.142/Less-46/?sort1%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)--http://172.16.1.142/Less-46/?sort1%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)-- 二.查表 http://172.16.1.142/Les…