JavaWeb02-MyBatis

目录

一、MyBatis

1.概述

2.JavaEE三层架构简单介绍

(1)表现层

(2)业务层

(3)持久层

3.框架

4.优势

(1)JDBC的劣势

(2)MyBatis优化

5.使用

(1)快速上手

(2)框架使用部分

(3)编码部分

6.Mapper代理开发

(1)Mapper代理开发的好处

(2)Mapper代理使用步骤

7.Mybatis的配置文件说明

8.查询过程出现的问题

9.xml文件中编写SQL语句没有提示

10.查操作

(1)单条件查询

(2)多条件查询

11.动态查询

(1)多条件动态查询

(2)单条件动态查询(多选一)

12.增操作

(1)主键返回

13.删操作

14.改操作

(1)修改字段数据

(2)修改动态字段数据

15.删操作

(1)单个删除

(2)批量删除

16.Mybatis参数传递

(1)单个参数

(2)多个参数

17.注解方式完成增删改查


一、MyBatis

1.概述

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

  • MyBatis 本是Apache 的一个开源项目iBatis,2010年这个项目由apache softwarefoundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github

  • 网址:mybatis – MyBatis 3 | 简介

辅助插件:MybatisX

2.JavaEE三层架构简单介绍

(1)表现层

页面展示

(2)业务层

逻辑处理

(3)持久层

负责将数据到保存到数据库的那一层代码

3.框架

  • 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型

  • 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展

4.优势

(1)JDBC的劣势
  • 硬编码

    • 注册驱动,获取连接

    • SQL语句

  • 操作较繁琐

    • 手动设置参数

    • 手动封装结果集

(2)MyBatis优化

MyBatis 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作

5.使用

(1)快速上手

框架使用部分:

  • 创建模块,导入坐标

  • 编写核心配置文件

  • 编写SQL映射文件

编码部分:

  • 定义实体类(POJO类)

  • 加载核心配置文件,获取SqlSessionFactory对象

  • 获取SqlSession对象

  • 释放资源

(2)框架使用部分
  • 导入坐标

     
   <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
<!--        mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
​
        <!-- 添加slf4j日志api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.20</version>
        </dependency>
        <!-- 添加logback-classic依赖 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- 添加logback-core依赖 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>

  • 核心配置文件,文件名通常:mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
<!--                数据库连接信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///test?useSSL=false&amp;useServerPrepStmts=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
<!--        加载SQL的映射文件-->
        <mapper resource="ProductMapper.xml"/>
    </mappers>
</configuration>

  • 编写SQL映射文件,名称:要操作的表名+Mapper(ProductMapper.xml)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
    namespace:名称空间
​
-->
<mapper namespace="product">
<!--
    id:sql语句的唯一标识
    resultType:返回结果类型
-->
    <select id="selectAll" resultType="pojo.Product">
        select * from Product;
    </select>
</mapper>

如果映射文件SQL语句中表名爆红,只是警告,并不影响实际操作

产生原因:ldea和数据库没有建立连接,不识别表信息

解决方法:用IDEA与数据库建立连接即可

(3)编码部分
  • 定义实体类

要与数据库中的数据类型对应

  • 使用

public class MybatisDemo {
    public static void main(String[] args) throws IOException {
//        1.加载核心配置文件,直接从官网粘过来就行了,获取SqlSessionFactory对象
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
​
//        2.获取sqlSession对象
        final SqlSession sqlSession = sqlSessionFactory.openSession();
​
//        3.执行SQL
        final List<Product> list = sqlSession.selectList("product.selectAll");
​
        System.out.println(list);
//        4.释放资源
        sqlSession.close();
​
    }
}

6.Mapper代理开发

(1)Mapper代理开发的好处
  • 解决原生方式中的硬编码(更安全)

  • 简化后期执行SQL

(2)Mapper代理使用步骤
  • 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下

检查方式:编译项目

在文件夹中打开

如下图即为成功

  • 设置SQL映射文件的namespace属性为Mapper接口全限定名

  • 在Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致

如果Mapper接口名称和SQL映射文件名称相同,并且在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载,如下图

  • 编码

    • 通过 SqlSession的 getMapper方法获取 Mapper接口的代理对象

    • 调用对应方法完成sql的执行

//        3.执行SQL
//        3-1.获取接口的代理对象
        final ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);
        final List<Product> products = mapper.selectAll();
        products.forEach(product -> System.out.println(product));

7.Mybatis的配置文件说明

可访问网址查看,后续再补

8.查询过程出现的问题

如以下情况

原因:实体类属性名称与数据库字段名称不一致,导致不能自动封装数据

解决方法一:

  • 为数据库字段起别名,让其和实体类属性名称一致(麻烦,不推荐)

方法一的优化方案:

  • 写一个SQL语句块,不灵活,还是不推荐~

解决方法二:

  • 结果映射,resultMap【有两个子标签,一个result,一个id,其中id子标签用来完成主键字段的映射,result用来映射普通字段的映射,使用方法与result一致】

  • type支持别名

再次运行

9.xml文件中编写SQL语句没有提示

在xml文件中按alt+enter

往下拉,根据安装的数据库选择合适的即可

10.查操作

(1)单条件查询
<!--
    参数占位符:
    1.#{}:将其替换为?,为了防止SQL注入。      使用场景:参数传递
    2.${}:拼SQL,存在SQL注入问题。           使用场景:表名或列名不固定的情况,但要注意SQL注入问题
​
    参数类型:parameterType,可以省略
​
    特殊字符处理:
    1.转义字符:适合少量
    2.CDATA区:适合大量,CD回车即可
-->
    <select id="selectById"  resultMap="resultMap_Employee">
        select * from employees where emp_no = #{id}
    </select>
​
    <resultMap id="resultMap_Employee" type="employee">
<!--        将不一样的属性名写一下即可-->
        <result column="emp_no" property="empNo"/>
        <result column="birth_date" property="birthDate"/>
        <result column="first_name" property="firstName"/>
        <result column="last_name" property="lastName"/>
        <result column="hire_date" property="hireDate"/>
​
    </resultMap>

(2)多条件查询

Mybatis提供了三种方式:

mapper.xml:

<select id="selectByCondition01" resultMap="resultMap_Employee">
    select *
    from employees
    where emp_no > #{empNo}
    and gender = #{gender}
</select>
​
<select id="selectByCondition02" resultMap="resultMap_Employee">
    select *
    from employees
    where emp_no > #{empNo}
      and gender = #{gender}
</select>
​
<select id="selectByCondition03" resultMap="resultMap_Employee">
    select *
    from employees
    where emp_no > #{empNo}
      and gender = #{gender}
</select>
​
    <resultMap id="resultMap_Employee" type="employee">
<!--        将不一样的属性名写一下即可-->
        <result column="emp_no" property="empNo"/>
        <result column="birth_date" property="birthDate"/>
        <result column="first_name" property="firstName"/>
        <result column="last_name" property="lastName"/>
        <result column="hire_date" property="hireDate"/>
​
    </resultMap>

pojo实体类:

public class Employee {
    private Integer empNo;
    private Date birthDate;
    private String firstName;
    private String lastName;
    private Character gender;
    private Date hireDate;
​
    public Employee() {
    }
​
    public Employee(Integer empNo, Character gender) {
        this.empNo = empNo;
        this.gender = gender;
    }
​
    public Employee(Integer empNo, Date birthDate, String firstName, String lastName, Character gender, Date hireDate) {
        this.empNo = empNo;
        this.birthDate = birthDate;
        this.firstName = firstName;
        this.lastName = lastName;
        this.gender = gender;
        this.hireDate = hireDate;
    }
​
    public Integer getEmpNo() {
        return empNo;
    }
​
    public void setEmpNo(Integer empNo) {
        this.empNo = empNo;
    }
​
    public Date getBirthDate() {
        return birthDate;
    }
​
    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }
​
    public String getFirstName() {
        return firstName;
    }
​
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
​
    public String getLastName() {
        return lastName;
    }
​
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
​
    public Character getGender() {
        return gender;
    }
​
    public void setGender(Character gender) {
        this.gender = gender;
    }
​
    public Date getHireDate() {
        return hireDate;
    }
​
    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }
​
    @Override
    public String toString() {
        return "Employee{" +
                "empNo=" + empNo +
                ", birthDate=" + birthDate +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", gender=" + gender +
                ", hireDate=" + hireDate +
                '}';
    }
}

mapper.EmployeeMapper

/**
 * 条件查询01
 * 查询员工工号>?且性别为?的所有员工信息
 * *参数接收方式
 * 1.散装参数:如果方法中有多个参数,需要使用@Param("SQL参数占位符名称”)
 * @param empNo 员工工号
 * @param character 性别
 * @return Employee对象集合
 */
List<Employee> selectByCondition01(@Param("empNo")int empNo,@Param("gender")Character character);
​
/**
 * 条件查询02:实体类封装参数
 * @param employee 员工对象,注意对象的属性名称要和SQL参数占位符名称一致
 * @return 员工对象集合
 */
List<Employee> selectByCondition02(Employee employee);
​
/**
 * 条件查询03:map集合
 * @param map map集合,要保证SQL中的参数占位符名称和map集合的键名称一致
 * @return 员工对象集合
 */
List<Employee> selectByCondition03(Map map);

测试:

@Test
public void selectByCondition01() throws IOException {
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
​
    final SqlSession sqlSession = sqlSessionFactory.openSession();
​
    final List<Employee> employees = sqlSession.getMapper(EmployeeMapper.class).selectByCondition01(10001, 'F');
    employees.forEach(employee -> System.out.println(employee));
    sqlSession.close();
}
    @Test
    public void selectByCondition022() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
​
        final SqlSession sqlSession = sqlSessionFactory.openSession();
​
//        final List<Employee> employees = sqlSession.getMapper(EmployeeMapper.class).selectByCondition02(new Employee(10001,'F'));
        Employee employee = new Employee();
        employee.setEmpNo(10001);
        employee.setGender('F');
        final List<Employee> employees = sqlSession.getMapper(EmployeeMapper.class).selectByCondition02(employee);
        employees.forEach(e -> System.out.println(e));
        sqlSession.close();
    }
@Test
public void selectByCondition03() throws IOException {
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
​
    final SqlSession sqlSession = sqlSessionFactory.openSession();
    
    Map map = new HashMap();
    Integer empNo = 10001;
    Character gender = 'F';
    map.put("empNo",empNo);
    map.put("gender",gender);
​
    final List<Employee> employees = sqlSession.getMapper(EmployeeMapper.class).selectByCondition03(map);
    employees.forEach(e -> System.out.println(e));
    sqlSession.close();
}

11.动态查询

SQL语句会随着用户的输入或外部条件的变化而变化,我们称为 动态SQL

mybatis对动态SQL用很大的支撑

  • if:条件判断

    • test:逻辑判断

  • choose(when,otherwise)

  • trim(where,set)

  • foreach

更具体的可查阅官网,动态SQL

(1)多条件动态查询

修改一下:

<select id="selectByCondition03" resultMap="resultMap_Employee">
    select *
    from employees
    where
        <if test="empNo != null and empNo != ''">
            emp_no > #{empNo}
        </if>
        <if test="gender !=null ">
            and gender = #{gender}
        </if>
​
</select>

测试时会发现如果没有第一个参数后面会报错

解决方法:

  • 第一种方法:统一格式,第一个条件为一个恒等式

            where
#             恒等式
            <if test="empNo != null and empNo != ''">
                and emp_no > #{empNo}
            </if>
            <if test="gender !=null ">
                and gender = #{gender}
            </if>
  • 第二种方法:使用< where >标签替换where关键字

<where>
    <if test="empNo != null and empNo != ''">
        and emp_no > #{empNo}
    </if>
    <if test="gender !=null ">
        and gender = #{gender}
    </if>
</where>

测试:

(2)单条件动态查询(多选一)
<select id="selectByConditionSingle" resultMap="resultMap_Employee">
        select * from employees
    where
        <choose>
            <when test="empNo != null">
                emp_no > #{empNo}
            </when>
            <when test="gender !=null">
                gender = #{gender}
            </when>
            <when test="lastName != null">
                last_name like #{lastName}
            </when>
            <otherwise>
<!--                相当于java switch中的default,写个恒等式即可-->
                
                1 = 1
            </otherwise>
        </choose>
    </select>

或者

<where>
    <choose>
        <when test="empNo != null">
            emp_no > #{empNo}
        </when>
        <when test="gender !=null">
            gender = #{gender}
        </when>
        <when test="lastName != null">
            last_name like #{lastName}
        </when>
    </choose>
</where>

12.增操作

<insert id="add">
    insert into employees
        (first_name,last_name,gender,birth_date,hire_date)
    VALUES
        (#{firstName},#{lastName},#{gender},#{birthDate},#{hireDate})
</insert>

测试的时候会发现代码运行成功但并没有数据!

打开日志,会发现roll back了

观察日志就会发现 -Setting autocommit to false on JDBC Connection

所以在增操作后,需要使用commit()手动提交一次事务!

再次运行,数据添加成功

如果不想手动提交,可在openSession()传递布尔值以开启是否自动提交

  • mybatis默认是开启事务的

(1)主键返回

目的:添加完数据后,获取该数据的id值

<insert id="add" useGeneratedKeys="true" keyProperty="empNo">
    insert into employees
        (first_name,last_name,gender,birth_date,hire_date)
    VALUES
        (#{firstName},#{lastName},#{gender},#{birthDate},#{hireDate})
</insert>

13.删操作

同增

14.改操作

(1)修改字段数据
void update(Employee employee);
<update id="update">
    update employees
    set
        first_name = #{firstName},
        last_name = #{lastName},
        gender = #{gender}
    where emp_no = #{empNo}
</update>

(2)修改动态字段数据
<update id="update02">
    update employees
    <set>
        <if test="firstName != null and firstName != ''">
            first_name = #{firstName},
        </if>
        <if test="lastName != null and lastName != ''">
            last_name = #{lastName}
        </if>
    </set>
    where emp_no = #{empNo}
​
</update>

15.删操作

(1)单个删除
void deleteById(Integer empNo);
<delete id="deleteById">
    delete
    from employees
    where emp_no = #{empNo}
</delete>
(2)批量删除
/**
 * 批量删除
 * @param empNos id数组
 */
void deleteByIds(@Param("empNos") Integer[] empNos);
<!--    mybatis会将数组参数封装为一个map集合
        默认 key = array
            value = 对应数组
        可以使用@Param改变map集合的默认key名称
        foreach属性:separator分隔符
            -->
<delete id="deleteByIds">
    delete from employees
    where emp_no in
    <foreach collection="empNos" item="empNo" separator="," open="(" close=")">
        #{empNo}
    </foreach>
    ;
</delete>

/**
 * 批量删除02
 * @param empNos id数组
 */
void deleteByIds02(Integer[] empNos);
<delete id="deleteByIds02">
    delete from employees
    where emp_no in (
    <foreach collection="array" item="empNo" separator=",">
        #{empNo}
    </foreach>
    );
​
</delete>

测试

Integer[] integers = {10023,10024,10025,10026,10027,10018,10019,10020,10021,10022};
try {
    sqlSession.getMapper(EmployeeMapper.class).deleteByIds(integers);
    sqlSession.commit();
} catch (Exception e) {
    System.out.println("删除失败");
    e.printStackTrace();
}

16.Mybatis参数传递

(1)单个参数
  • pojo实体类:直接使用,属性名和参数占位符名称一致即可

  • Map集合:直接使用,键名和参数占位符名称一致即可

  • Collection:封装为map

  • List:封装为map

  • Array:封装为map

  • 其他:直接使用

(2)多个参数
  • 会将参数列表封装为map集合,由于默认可读性太差,可以使用@Param替换Map集合中默认的arg键名

  • map.put(”arg0“,参数值1)

  • map.put(”param1“ ,参数值1)

  • map.put(”param2“,参数值2)

  • map.put(”arg1“,参数值2)

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

封装方法为getNamedParams

  1. 在IDEA中,按住ctrl+shift+a打开action

  2. 将 ParamNameResolver粘进搜索框,选择Classes

  3. 搜索出来第一个就是,点进去

  4. 之后ctrl f。在搜索框输入getNamedParams

17.注解方式完成增删改查

使用注解方式会比配置文件开发更加高效

  • 查询:@Select

  • 添加;@Insert

  • 修改:@Update

  • 删除:@Delete

/**
 * 根据id查询
 * @param empNo id
 * @return Employee对象
 */
@Select("select * from employees where emp_no = #{empNo}")
Employee selectById(int empNo);

注意:

  • 注解完成简单功能

  • 配置文件完成复杂功能,(动态SQL)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法刷题:移动零

移动零 .题目链接详解curdesc算法原理 答案 . 题目链接 移动零 详解 题目要求我们要把数组中所有的零都移动到数组的末尾,且要求其余数字顺序不改变.这道题,我们使用到的是双指针算法: 利用两个指针,将数组分为三个部分, 三个区间分别为 [0,desc][desc1,cur-1][cur,n-1] 在…

HTML 标签

HTML&#xff1a;超文本标记语言 HTML骨架结构&#xff1a; html标签&#xff1a;网页的整体 head标签&#xff1a;网页的头部 body标签&#xff1a;网页的身体 HTML的注释 VS code中&#xff1a;ctrl/ 浏览器不会执行注释 HTML标签的构成&#xff1a; 双标签&#xff1a…

DC-9靶机渗透详细流程

信息收集&#xff1a; 1.存活扫描&#xff1a; arp-scan -I eth0 -l 发现靶机ip&#xff1a;192.168.10.132 └─# arp-scan -I eth0 -l 192.168.10.1 00:50:56:c0:00:08 (Unknown) 192.168.10.2 00:50:56:e5:b1:08 (Unknown) 192.168.10.132 //靶机 00:0c…

物联网和工业4.0

在当今这个快速发展的技术时代&#xff0c;物联网&#xff08;IoT&#xff09;和工业4.0成为了推动全球进入新工业时代的两大驱动力。对于刚入行的人来说&#xff0c;深入理解这两个概念及其背后的技术原理&#xff0c;对于把握未来的职业机会至关重要。 物联网&#xff0c;简…

备战蓝桥杯---动态规划(理论基础)

目录 动态规划的概念&#xff1a; 解决多阶段决策过程最优化的一种方法 阶段&#xff1a; 状态&#xff1a; 决策&#xff1a; 策略&#xff1a; 状态转移方程&#xff1a; 适用的基本条件 1.具有相同的子问题 2.满足最优子结构 3.满足无后效性 动态规划的实现方式…

Go内存优化与垃圾收集

Go提供了自动化的内存管理机制&#xff0c;但在某些情况下需要更精细的微调从而避免发生OOM错误。本文介绍了如何通过微调GOGC和GOMEMLIMIT在性能和内存效率之间取得平衡&#xff0c;并尽量避免OOM的产生。原文: Memory Optimization and Garbage Collector Management in Go 本…

2024-02-08(Flume)

1.Flume 的架构和MQ消息队列有点类似 2.Flume也可以做数据的持久化操作 在Channel部分选择使用File channel组件 3.Flume进行日志文件监控 场景&#xff1a;企业中应用程序部署后会将日志写入到文件中&#xff0c;我们可以使用Flume从各个日志文件将日志收集到日志中心以便…

用bootstrap结合jQuery实现简单的模态对话框

嗨害嗨&#xff0c;我又来了奥。今天呢&#xff0c;给大家分享一个工作中常用到的插件——模态对话框的用法。想必大家在工作中也遇到很多页面&#xff0c;需要用模态对话框进行交互的吧&#xff0c;现在呢&#xff0c;就让我们一起来了解一下它的使用吧。 首先&#xff0c;我…

Dlib检测人脸特征点标号图

dlib进行人脸检测时候&#xff0c;所有人脸的标号图&#xff0c;c检索的时候注意从0索引开始

Infuse通过Alist添加115网盘资源

说明 通过Alist代理管理115网盘&#xff0c;Infuse再添加Alist代理的115网盘的WebDAV 准备一台Linux服务器安装Alist 我这里用的华为云CentOS7&#xff0c;使用Docker容器 安装Alist docker run -d --restartalways -v /etc/alist:/opt/alist/data -p 5244:5244 -e PUID0 …

深入浅出:Golang的Crypto/SHA256库实战指南

深入浅出&#xff1a;Golang的Crypto/SHA256库实战指南 介绍crypto/sha256库概览主要功能应用场景库结构和接口实例 基础使用教程字符串哈希化文件哈希化处理大型数据 进阶使用方法增量哈希计算使用Salt增强安全性多线程哈希计算 实际案例分析案例一&#xff1a;安全用户认证系…

跟着pink老师前端入门教程-day23

苏宁网首页案例制作 设置视口标签以及引入初始化样式 <meta name"viewport" content"widthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scale1.0"> <link rel"stylesheet" href"css/normaliz…

如何从格式化的 U盘恢复不见的数据

格式化与使用任何容量有限的存储设备&#xff08;例如 USB 闪存驱动器&#xff09;密切相关。在大多数情况下&#xff0c;一次性删除所有内容比逐个删除文件更快、更方便。但是&#xff0c;如果您犯了错误并意外格式化了错误的驱动器怎么办&#xff1f;是否可以从格式化的闪存驱…

C++重新入门-C++运算符

目录 1. 算术运算符 2. 关系运算符 3.逻辑运算符 4.位运算符 5.赋值运算符 6.杂项运算符 7.C 中的运算符优先级 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 内置了丰富的运算符&#xff0c;并提供了以下类型的运算符&#xff1a; 算术运算符关系运算符逻…

Python入门:常用模块—os模块及sys模块

os模块 sys模块 import sys print(sys.argv) # 命令参数list&#xff0c;第一个元素是程序本身路径 print(sys.exit()) # 退出程序&#xff0c;正常退出是exit(0) print(sys.version) # 获取python解释程序的版本信息 print(sys.maxint()) # 最大…

用EXCEL从地址(上海)中提取各区(浦东新区等区)信息

背景&#xff1a; 朋友工作需要经常用EXCEL把各上海用户收货地址中的区提取出来&#xff0c;之前一直手动处理&#xff0c;希望我帮忙用EXCEL公式直接提取处理。 数据样式&#xff1a; 中国上海市浦东新区A小区 上海徐汇区B小区 中国&#xff0c;上海&#xff0c;浦东新区&a…

fast.ai 机器学习笔记(二)

机器学习 1&#xff1a;第 5 课 原文&#xff1a;medium.com/hiromi_suenaga/machine-learning-1-lesson-5-df45f0c99618 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 来自机器学习课程的个人笔记。随着我继续复习课程以“真正”理解它&#xff0c;这些笔记将继续更…

Scrum敏捷开发管理全流程-敏捷管理工具

Leangoo领歌是款永久免费的专业的敏捷开发管理工具&#xff0c;提供端到端敏捷研发管理解决方案&#xff0c;涵盖敏捷需求管理、任务协同、进展跟踪、统计度量等。 Leangoo领歌上手快、实施成本低&#xff0c;可帮助企业快速落地敏捷&#xff0c;提质增效、缩短周期、加速创新。…

分享76个表单按钮JS特效,总有一款适合您

分享76个表单按钮JS特效&#xff0c;总有一款适合您 76个表单按钮JS特效下载链接&#xff1a;https://pan.baidu.com/s/1CW9aoh23UIwj9zdJGNVb5w?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集…

基于SpringBoot+Vue的服装销售商城系统

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是墨韵&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c;不进则退。学习如赶路&#xff0c;不能慢一步。 目录 一、项目简介 二、开发技术与环…