MyBatis——增删改查

news2024/11/24 0:58:02

核心配置文件

MyBatis核心配置文件的顶层结构如下:

<environments> 元素

<typeAliases>元素

作用:

 

 

配置文件完成增删改查

准备环境

创建数据库表tb_brand
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand(
-- id主键
id int primary key auto_increment,
-- 品牌名称
brand_name varchar(20),
-- 企业名称
company_name varchar(20),
-- 排序字段
ordered int,
-- 描述信息
description varchar(100),
-- 状态:0:禁用 1:启用
status int
);
-- 添加数据
insert into tb_brand(brand_name,company_name, ordered, description,status)
values ('三只松鼠','三只松鼠股份有限公司',5,'好吃不上火',0),
('华为','华为技术有限公司',100,'华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界',1),
('小米','小米科技有限公司',50,'are you ok',1);

执行查询语句

实体类Brand
package com.mybatisDemo.pojo;

/**
 * @author hyk~
 */
public class Brand {
    //id 主键
    private Integer id;
    //品牌名称
    private String brandName;
    //企业名称
    private String companyName;
    //描述信息
    private String description;
    //状态: 0:禁用   1:启用
    private Integer status;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "Brand{" +
                "id=" + id +
                ", brandName='" + brandName + '\'' +
                ", companyName='" + companyName + '\'' +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
}
测试用例

安装MyBatisX插件

MybatisX是一款基于IDEA的快速开发插件,为效率而生
主要功能
XML和接口方法相互跳转
根据接口方法生成statement

安装完成后:自动创建

查询

(1)定义接口方法

(2)编写SQL映射文件

(3)执行测试方法

1.查询所有数据

运行结果出现异常,brandName和companyName查询为空值

原因:数据库表的字段名称 和 实体类的属性名称 不一样,则不能自动封装数据

解决方案1:

起别名:对不一样的列名起别名,让别名和实体类的属性名一样

*缺点:每次查询都要定义一次别名

解决方案2:

缺点:不灵活

解决方案3:

总结

实体类属性名和数据库表列名不一致,不能自动封装数据
1)起别名:在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样

*可以定义<sql>片段,提升复用性

2) resultMap:定义<resultMap>完成不一致的属性名和列名的映射

2.查看详情

定义接口方法

编写SQL映射文件

 参数占位符:

1. #{}:会将其替换为 ?,为了防止SQL注入

2. ${}: 拼接sql。会存在SQL注入问题

3. 使用时机: 

参数传递的时候: #{}

表名或者列名不固定的情况下: ${}

参数类型:parameterType 可以省略

特殊字符处理:

1.转义字符 例如:< 转义字符为 &lt;

2.CDATA区

 

编写测试方法

@Test
    public void testSelectById() throws IOException {
        //接收id参数
        int id = 1;

        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,执行SQL语句
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //获取BrandMapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        Brand brand = brandMapper.selectById(id);

        //打印
        System.out.println(brand);

        //释放资源
        sqlSession.close();
    }

运行


3.条件查询

多条件查询

参数接收

1.散装参数

如果方法中有多个参数,需要使用@Param("SQL参数占位符名称”)

定义接口方法

 编写SQL映射文件

执行测试方法

@Test
    public void testSelectTerm() throws IOException {
        //接收多条件查询参数
        int status = 1;
        String brandName ="米";
        String companyName = "科技";

        //数据处理
        brandName = "%" + brandName+ "%";
        companyName = "%" + companyName+ "%";

        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,执行SQL语句
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //获取BrandMapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        List<Brand> brands = brandMapper.selectTerm(status, brandName, companyName);

        //打印
        System.out.println(brands);

        //释放资源
        sqlSession.close();
    }

运行结果

2.对象参数

定义接口方法

SQL映射文件无需变更

测试方法

其它代码无需更改,只需封装对象

并修改传参

运行未报错则成功

3.map集合参数

定义接口方法

SQL映射文件无需变更

测试方法

创建Map集合

修改传参

运行未报错则成功

总结

(1)散装参数: 需要使用@Param(“SQL中的参数占位符名称”)
(2)实体类封装参数:只需要保证sQL中的参数名和实体类属性名对应上,即可设置成功

(3)map集合:只需要保证SQL中的参数名和map集合的键的名称对应上,即可设置成功

4.多条件-动态条件查询

只需更改SQL映射文件

动态条件查询

if:条件判断

test:逻辑表达式

问题:

如果第一个条件为空,则会出现语法错误 :select * from tb_brand where and .... (第一个条件不需要逻辑运算符)

解决方案:

恒等式:where 1 = 1 没有特殊含义 只是为了语法正确

<where>标签 替换 where 关键字

5.单条件-动态条件查询

从多个条件中选择一个
choose(when,otherwise): 选择,类似于Java 中的 switch 语句

定义接口方法

编写SQL映射文件

编写测试文件

@Test
    public void selectTermSingle() throws IOException {
        //接收多条件查询参数
        int status = 1;
        String brandName ="米";
        String companyName = "";

        //数据处理
        brandName = "%" + brandName+ "%";
        companyName = "%" + companyName+ "%";

        //封装对象
        Brand brand = new Brand();
//        brand.setStatus(status);
//        brand.setBrandName(brandName);
//        brand.setCompanyName(companyName);

        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,执行SQL语句
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //获取BrandMapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

//        List<Brand> brands = brandMapper.selectTerm(brand);

        List<Brand> brands = brandMapper.selectTermSingle(brand);

        //打印
        System.out.println(brands);

        //释放资源
        sqlSession.close();
    }

可取消注释尝试各个方案

运行

添加

编写接口方法

编写SQL映射文件

测试方法

 @Test
    public void addData() throws IOException {
        //接收参数
        String brandName ="vivo";
        String companyName = "维沃通信有限公司";
        int ordered = 1000;
        String description = "点燃生活激情,vivo与你共创无限可能";
        int status = 0;

        //封装对象
        Brand brand1 = new Brand();
        brand1.setBrandName(brandName);
        brand1.setCompanyName(companyName);
        brand1.setOrdered(ordered);
        brand1.setDescription(description);
        brand1.setStatus(status);

        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,执行SQL语句
        //填入 true 表示自动提交事务
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //获取BrandMapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);


        boolean b = brandMapper.addData(brand1);

        //打印
        if (b == true)
            System.out.println("数据添加成功");

        if (b == false)
            System.out.println("数据添加失败");

        //手动提交事务 否则数据添加成功但无法查询到 数据库回滚
        //sqlSession.commit();

        //释放资源
        sqlSession.close();
    }

开启自动提交事务才能正常添加且查询到数据 

手动提交也可以

运行结果为数据添加成功

点开数据库执行查询语句发现已经有该条数据了

MyBatis事务
openSession():默认开启事务,进行增删改操作后需要使用

sqlSession.commit();手动提交事务

openSession(true): 可以设置为自动提交事务(关闭事务)

1.添加-主键返回

在数据添加成功后,需要获取插入数据库数据的主键的值

比如:添加订单和订单项
1.添加订单
2.添加订单项,订单项中需要设置所属订单的id

返回添加数据的主键

<insert useGeneratedKeys="true" keyProperty="id">

编写测试代码

运行

修改

1.修改全部字段

定义接口方法

编写SQL映射文件

执行测试方法

@Test
    public void updateData() throws IOException {
        //接收参数
        int id = 1;
        String brandName ="HONOR";
        String companyName = "荣耀手机有限公司";
        int ordered = 500;
        String description = "荣耀之路,始于创新,终于卓越。";
        int status = 1;

        //封装对象
        Brand brand1 = new Brand();
        brand1.setId(id);
        brand1.setBrandName(brandName);
        brand1.setCompanyName(companyName);
        brand1.setOrdered(ordered);
        brand1.setDescription(description);
        brand1.setStatus(status);

        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,执行SQL语句
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //获取BrandMapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);


        int i = brandMapper.updateData(brand1);


        //打印
        if (i != 0)
            System.out.println("数据修改成功,影响的行数为"+i+"行");
        if (i == 0)
            System.out.println("数据修改失败");
        
        //手动提交事务 否则数据添加成功但无法查询到 数据库回滚
        //sqlSession.commit();

        //释放资源
        sqlSession.close();
    }

将原先id为1的数据三只松鼠改成HONOR的数据

运行代码

显示数据修改成功并且影响行数为1行

查看数据库表显示已经修改完成了

2.修改动态字段

定义接口方法

编写SQL映射文件

执行测试方法

//修改动态数据
    @Test
    public void updateTrendsData() throws IOException {
        //接收参数
        int id = 1;
        String brandName ="HONOR-HUAWEI";
        String companyName = "华为荣耀手机有限公司";
        int ordered = 500;
        String description = "荣耀之路,始于创新,终于卓越。";
        int status = 1;

        //封装对象
        Brand brand1 = new Brand();
        brand1.setId(id);
        brand1.setBrandName(brandName);
        brand1.setCompanyName(companyName);
        brand1.setOrdered(ordered);
        brand1.setDescription(description);
        brand1.setStatus(status);

        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,执行SQL语句
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //获取BrandMapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);


        int i = brandMapper.updateTrendsData(brand1);


        //打印
        if (i != 0)
            System.out.println("数据修改成功,影响的行数为"+i+"行");
        if (i == 0)
            System.out.println("数据修改失败");

        //手动提交事务 否则数据添加成功但无法查询到 数据库回滚
        //sqlSession.commit();

        //释放资源
        sqlSession.close();
    }

主要是这一段代码

运行代码

由此可见已实现动态修改数据了

删除

1.删除一个

定义接口方法 根据id删除数据

编写SQL映射文件

执行测试方法

    //删除一条数据
    @Test
    public void deleteData() throws IOException {
        //接收参数
        int id = 5;

        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,执行SQL语句
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //获取BrandMapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        boolean b = brandMapper.deleteData(id);

        //打印
        if (b == true)
            System.out.println("数据删除成功");
        if (b == false)
            System.out.println("数据删除失败");

        //手动提交事务 否则数据添加成功但无法查询到 数据库回滚
        //sqlSession.commit();

        //释放资源
        sqlSession.close();
    }

删除id为5的数据

执行代码

提示数据删除成功,再次查看数据表

数据表中已无id为5的数据 表示删除成功了


2.批量删除

定义接口方法

编写SQL映射文件

MyBatis会将数组参数,封装成一个Map结合

*默认: array = 数组         collection="array"

*也可以使用 @Param("ids")注解改变Map集合的默认key的名称         collection="ids"

利用循环遍历ids数组中的数据 有几个id数据就会生成几个#{id}

separator="," 分隔符

open="("        开始的拼接

close=");"      结束时的拼接

查看数据表中数据

执行测试方法

    //批量删除数据
    @Test
    public void deleteDataByIds() throws IOException {
        //接收数组参数
        int [] ids = {4,5,6};

        //1.获取SqlSessionFactory
        String resource = "mybatis-config.xml"; //核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,执行SQL语句
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //获取BrandMapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        boolean b = brandMapper.deleteDataByIds(ids);

        //打印
        if (b == true)
            System.out.println("数据删除成功");
        if (b == false)
            System.out.println("数据删除失败");

        //手动提交事务 否则数据添加成功但无法查询到 数据库回滚
        //sqlSession.commit();

        //释放资源
        sqlSession.close();
    }

删除数组中包含的id数据

运行

查看数据表已经没有id为4,5,6的数据了

MyBatis参数传递

MyBatis 接口方法中可以接收各种各样的参数,MyBatis底层对于这些参数进行不同的封装处理方式

单个参数

1.POJO类型 直接使用,属性名 和 参数占位符 名称 一致

2.Map集合 直接使用,键名 和 参数占位符 名称 一致

3.Collection 封装为Map集合 可以使用@Param注解,替换Map集合中默认的arg键名

map.put("arg0",collection集合);

map.put("collection",collection集合);

4.List 封装为Map集合 可以使用@Param注解,替换Map集合中默认的arg键名
 

map.put("arg0",list集合);

map.put("collection",List集合);

map.put("List",List集合);

5.Array 封装为Map集合 可以使用@Param注解,替换Map集合中默认的arg键名
 

map.put("arg0",数组);

map.put("array”,数组);

6.其他类型 直接使用

7.多个参数:

封装为Map集合 可以使用@Param注解,替换Map集合中默认的arg键名

map.put("arg0",参数值1)

map.put("param1",参数值1)

map.put("param2",参数值2)

map.put("arg1",参数值2)

-------------@Param("username")

map.put("username",参数值1)

map.put("param1",参数值1)

map.put("param2",参数值2)

map.put("arg1",参数值2) 

MyBatis提供了 ParamNameResolver 类来进行参数封装

结论: 将来都使用@Param注解来修改Map集合中默认的键名

并使用修改后的名称来获取值,这样可读性更高

定义接口方法

编写SQL映射文件

执行 运行成功

注解开发

使用注解开发会比配置文件开发更加方便

格式:

@Select("select * from tb_user where id = #{id}")
User selectById(int id);

查询: @Select
添加: @Insert
修改: @Update
删除: @Delete

代码演示

定义接口方法并编写注解SQL语句

运行测试代码

总结:

注解完成简单功能
配置文件完成复杂功能 

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

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

相关文章

龙芯的 新世界 与 旧世界

但是基本可以 确定 旧世界应该是 有 mips 的代码的。 新世界 应该是 loongarch . 这是 龙芯派 2k300 的连接。 6.Github相关仓库 龙芯派相关源码仓库&#xff1a;https://github.com/LoongsonDotNETCommunity/LoongsonPI 龙芯派Cookbook仓库&#xff1a;https://github.com/L…

UML详解

1.what is the UML UML 全称是 Unified Modeling Language&#xff08;统一建模语言&#xff09;&#xff0c;它以图形的方式来描述软件的概念 2.它存在的目的 UML 的目标是通过一定结构的表达&#xff0c;来解决现实世界到软件世界的沟通问题。 3.什么是模&#xff0c;…

C++语法15 多分支结构(if多分支与switch结构)

if else if else 多分支结构基本框架 if&#xff08;条件1&#xff09;语句1; //满足条件1就执行 else if&#xff08;条件2&#xff09;语句2; //不满足条件1&#xff0c;但是满足条件2执行 else if (条件3&#xff09;语句3; //不满足条件1和条件2&#x…

【链表经典面试题】LeetCode138.复制带随机指针的链表(链表深拷贝)

&#x1f4c7;文章目录 &#x1f680;题目描述&#x1f680;思路1&#xff1a;&#x1f680;思路2&#xff1a;&#x1f680;完整代码 &#x1f680;题目描述 解读&#xff1a; 题目意思就是 给你一个链表 这个链表中除了有next指针之外 还有一个指向这个链表的随机位置的一个指…

在哪里可以查到一手的标讯信息?

标讯信息集招投标讯息的简称。在市场上&#xff0c;标讯是一种非常关键的信息&#xff0c;包括招标公告&#xff0c;文件&#xff0c;截止日期等关键内容&#xff0c;便于需求方和供应商进行业务合作。 对于企业来说&#xff0c;及时获取到最新的标讯信息是非常重要的&#xf…

安装VS Code 提示This User Installer is not meant to be run as an Administrator问题

目录预览 一、问题描述二、原因分析三、解决方案四、参考链接 一、问题描述 在vs code官网&#xff08;https://code.visualstudio.com/&#xff09;下载安装包&#xff0c;显示如下提示信息&#xff1a; This User Installer is not meant to be run as an Administrator.…

【vue大作业-端午节主题网站】【预览展示视频和详细文档】

vue大作业-端午节主题网站介绍 端午节&#xff0c;又称为龙舟节&#xff0c;是中国的传统节日之一&#xff0c;每年农历五月初五庆祝。这个节日不仅是纪念古代爱国诗人屈原的日子&#xff0c;也是家人团聚、共享美食的时刻。今天&#xff0c;我们非常高兴地分享一个以端午节为…

【字符串解析】IP地址字段解析提取函数接口

在嵌入式业务逻辑中&#xff0c;我们有时需要从配置文件、串口或者服务端接收的消息数据中进行字符串解析&#xff0c;来提取需要的目标字符串字段。通常我们会调用字符串处理相关的函数&#xff0c;例如strstr&#xff0c;strchr&#xff0c;sscanf等&#xff0c;再结合指针偏…

【验证码识别】Yolov8实战某验3空间推理点选验证码,目标检测,语义分割,颜色分类。

【验证码识别】Yolov8实战某验3空间推理点选验证码&#xff0c;目标检测&#xff0c;语义分割&#xff0c;颜色分类。 文章目录 【验证码识别】Yolov8实战某验3空间推理点选验证码&#xff0c;目标检测&#xff0c;语义分割&#xff0c;颜色分类。声明1.空间推理验证码&#xf…

C# OpenCvSharp 车牌颜色识别

C# OpenCvSharp 车牌颜色识别 目录 效果 项目 代码 下载 效果 项目 代码 using OpenCvSharp; using System; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; namespace OpenCvSharp_Demo { public partial class Form1 : Form { …

采购芯片时细心,再细心!

检查原理图&#xff0c;采购时候的细心对照所费的时远远少于焊完找BUG的时间&#xff01;&#xff01;&#xff01; 购买芯片的时候不光看芯片名称&#xff0c;封装&#xff0c;丝印也要看&#xff0c;如果不一样必须对照两者的引脚图仔细观察是否一样&#xff01;&#xff01…

扭蛋机小程序:深度探索虚拟寻宝之旅的乐趣

引言 扭蛋机小程序&#xff0c;这个融合了传统与创新的虚拟寻宝乐园&#xff0c;已经吸引了无数玩家的目光。在这个充满惊喜和挑战的虚拟世界里&#xff0c;每一个扭蛋都可能蕴藏着无尽的宝藏。本文将带您深入探索扭蛋机小程序的魅力所在&#xff0c;体验一场别开生面的虚拟寻…

上位机图像处理和嵌入式模块部署(h750 mcu vs f407)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 在目前工业控制上面&#xff0c;f103和f407是用的最多的两种stm32 mcu。前者频率低一点&#xff0c;功能少一点&#xff0c;一般用在低端的嵌入式设…

【数据结构与算法】运算受限的线性表(栈,队列)重要知识点详解

栈和队列是什么样的线性表? 栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;都是运算受限的线性表。 栈&#xff1a;栈是一种特殊的线性表&#xff0c;只允许在一端&#xff08;通常称为“顶端”&#xff09;进行插入和删除操作。栈遵循后进先出&#x…

CENTOS7.9下服务器双网卡bond模式6配置示例

​1.bond口的特点 bond口通过将多个网口进行聚合&#xff0c;多个网口聚合后一方面实现了大带宽传输&#xff0c;另外多网口聚合后也同时具有冗余特性&#xff0c;当其中一个网口down掉后&#xff0c;其他网口会继续转发流量&#xff0c;不会导致流量中断。 2.使用条件 当环境…

参数搜索流形学习

目录 一、网格搜索1、介绍2、代码示例 二、HalvingGridSearch1、介绍2、代码示例 三、随机搜索1、介绍2、代码示例 三、贝叶斯搜索1、介绍2、代码示例 四、参数搜索总结五、流形学习1、LLE1、介绍2、官方代码示例 2、t-SNE1、介绍2、官方代码示例 一、网格搜索 1、介绍 网格搜…

安卓手机最近删除照片如何找回?这些技巧来帮你!

我们时常会在手机上拍摄大量照片&#xff0c;记录下生活中的每一个瞬间。然而&#xff0c;由于存储空间不足、设备更新等原因&#xff0c;我们可能会不小心删除一些照片。最近删除照片如何找回&#xff1f;通过本文的介绍&#xff0c;您将了解到如何轻松找回最近删除的照片&…

2025计算机毕业设计选题题目推荐-毕设题目汇总大全

选题在于精&#xff0c;以下是推荐的容易答辩的选题&#xff1a; SpringBoot Vue选题: 基于SpringBoot Vue家政服务系统 基于SpringBoot Vue非物质文化遗产数字化传承 基于SpringBoot Vue兽医站管理系统 基于SpringBoot Vue毕业设计选题管理系统 基于SpringBoot Vue灾害应急救援…

群辉USB Copy套件的使用

目录 一、套件安装 二、插入USB设备 三、使用 四、故障排除 有了群辉NAS后,很多U盘、移动硬盘的数据需要备份到NAS中,这时就可以考虑使用USB Copy这个套件了。 USB Copy 乃是群晖上可用于和外接存储设备进行文件复制的一个工具,我常常借助它把外置存储设备的文件拷贝至…

程序猿大战Python——文件操作、异常、模块——异常介绍

什么是异常 目标&#xff1a;了解什么是异常&#xff1f; 异常指的是Python程序发生的不正常事件。 有时候&#xff0c;异常可称为错误。 当检测到一个错误时&#xff0c;Python解释器就无法继续执行&#xff0c;反而出现了一些错误的提示&#xff0c;这就是异常&#xff0c;…