【零基础入门MyBatis系列】第十一篇——动态SQL

news2025/8/2 20:34:33

一、概述

📖 1、什么是动态SQL?

  • 根据不同条件生成不同的SQL语句,是mybatis的一大优势。
  • 用于动态拼接SQL语句

📖 2、如何实现动态SQL?

  • mybatis 为我们提供了一些标签,在写SQL语句的时候,合理的使用这些标签可以提高SQL语句的效率
  • 该部分都用于Mapper映射文件的SQL语句中
  • 本章节内容概述:
    在这里插入图片描述

📖 3、准备工作:

  • 创建一个新模块:mybatis-009-dynamic-sql【Maven模块】
  • 修改 pom.xml 文件 – 打包方式jar、–引入依赖 mysql驱动、mybatisjunitlogback
  • 目录结构:
    在这里插入图片描述
  • 文件说明:
文件名作用
CarMapper数据库操作接口
CarMapper.xml映射文件
CarPOJO类
SqlSessionUtil工具类
jdbc.properties保存mysql账户信息
logback.xml日志配置文件
mybatis-config.xml核心配置文件
CarMapperTest单元测试文件
  • CarMapper、CarMapper.xml、CarMapperTest三个文件在本篇学习过程中不断更新,其他文件不动
  • 普通Java类 – Car
package com.powernode.mybatis.pojo;

/**
 * @author Bonbons
 * @version 1.0
 */
public class Car {
    private Long id;
    private String carNum;
    private String brand;
    private Double guidePrice;
    private String produceTime;
    private String carType;
    //提供构造方法
    public Car(){}

    public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType) {
        this.id = id;
        this.carNum = carNum;
        this.brand = brand;
        this.guidePrice = guidePrice;
        this.produceTime = produceTime;
        this.carType = carType;
    }
    //提供get和set方法

    public Long getId() {
        return id;
    }

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

    public String getCarNum() {
        return carNum;
    }

    public void setCarNum(String carNum) {
        this.carNum = carNum;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public Double getGuidePrice() {
        return guidePrice;
    }

    public void setGuidePrice(Double guidePrice) {
        this.guidePrice = guidePrice;
    }

    public String getProduceTime() {
        return produceTime;
    }

    public void setProduceTime(String produceTime) {
        this.produceTime = produceTime;
    }

    public String getCarType() {
        return carType;
    }

    public void setCarType(String carType) {
        this.carType = carType;
    }
    //重写toString方法

    @Override
    public String toString() {
        return "Car{" +
                "id=" + id +
                ", carNum='" + carNum + '\'' +
                ", brand='" + brand + '\'' +
                ", guidePrice=" + guidePrice +
                ", produceTime='" + produceTime + '\'' +
                ", carType='" + carType + '\'' +
                '}';
    }
}
  • 工具类:SqlSessionUtil
package com.powernode.mybatis.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 Bonbons
 * @version 1.0
 */
public class SqlSessionUtil {
    private SqlSessionUtil(){}

    //定义一个SqlSession
    private static final SqlSessionFactory sqlSessionFactory;
    //在类加载的时候初始化SqlSessionFactory
    static {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //定义一个全局的ThreadLocal,可以保证一个SqlSession对应一个线程
    private static ThreadLocal<SqlSession> local = new ThreadLocal<>();

    //通过一个公有的方法为外部提供会话的对象 >> 确保同一个线程操作的是同一个连接对象
    public static SqlSession openSession(){
        //我们用local去获取会话
        SqlSession sqlSession = local.get();
        //如果当前没有开启的会话就去创建一个,如果get到了就用这个[确保我们操作的是同一个连接对象]
        if(sqlSession == null){
            sqlSession = sqlSessionFactory.openSession();
            //将SqlSession对象绑定到当前线程上
            local.set(sqlSession);
        }
        return sqlSession;
    }

    /**
     * 关闭SqlSession对象并从当前线程中解绑
     * @param sqlSession 会话对象
     */
    public static void close(SqlSession sqlSession){
        if(sqlSession != null){
            sqlSession.close();
            local.remove();
        }
    }
}
  • properties文件 :jdbc.properties
jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/powernode
jdbc.username = root
jdbc.password = 111111
  • 日志配置文件:logback.xml
<?xml version="1.0" encoding="UTF-8"?>

<configuration debug="false">
    <!-- 控制台输出 -->
    <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 %logger{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>
  • mybatis 核心配置文件:mybatis-config.xml
<?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>
    <!--外部资源地址-->
    <properties resource="jdbc.properties"></properties>
    <settings>
        <!--开启自动映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <typeAliases>
        <!--pojo类包名,自动起简名-->
        <package name="com.powernode.mybatis.pojo"/>
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--指定xml的目录,加载目录下的所有映射文件,前提要与对应接口在一个目录下-->
        <package name="com.powernode.mybatis.mapper"/>
    </mappers>
</configuration>

二、if 标签

📖 1、if 标签如何使用?

用于多条件查询,在我们指定的几个条件中,我们可以为该条件传递参数,也可以不使用该查询条件
在这里插入图片描述
例如该图:如果我们想使用某个条件来筛选,我们就可以为其传入对应的有效参数

📖 2、if 标签的具体是如何使用的呢?

  • if 标签有一个test属性,只有当 test 属性为 true 时,才会拼接if里面的内容到SQL语句中
  • test 的属性值我们一般都传入判断当前参数是否有效的布尔表达式property != null and property != ''
  • if 语句当中就是我们要拼接的条件表达式

📖 3、那我们如何实现根据品牌、指导价、汽车类型来查询汽车数据呢?

  • 要求:根据品牌模糊查询、指导价大于指定的值、汽车类型为我们指定的类型【三个条件同时满足】
  • 因为返回的结果可能是多条,所以我们用一个集合来接收,为了使用见名知意的参数名,我们可以添加 @Param 注解【数据库表操作接口】
/**
* 多条件查询,可能使用这个条件,也可能不使用
* @param brand 品牌
* @param guidePrice 指导价
* @param carType 汽车类型
* @return 查询结果的集合
*/
List<Car> selectByMultiCondition(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType);
  • 有了接口我们就可以去写对应的映射文件:
<select id="selectByMultiCondition" resultType="Car">
        select * from t_car where 1=1
        <if test="brand != null and brand != ''">
            and brand like "%"#{brand}"%"
        </if>
        <if test="guidePrice != null and guidePrice != ''">
            and guide_price > #{guidePrice}
        </if>
        <if test="carType != null and carType != ''">
            and car_type = #{carType}
        </if>
</select>

为什么这里要添加 1 = 1 呢?

(1)因为如果 没有 if 标签有效的话,该SQL底层末尾的情况是这样的 select * from t_car where,很明显是个错误的语法
(2)添加1=1之后,条件都为空就会输出全部的汽车数据

  • 接下来在测试类中写个单元测试方法调试一下【考虑空值,可以有8种输入,经测试全部通过】
@Test
public void testSelectByMultiCondition(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectByMultiCondition("奔驰", 55.0, "燃油车");
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}

在这里插入图片描述


三、where 标签

  • where 标签可以让SQL子句更加智能
    • 可以自动去除前面多余的 and/or
    • 如果没有条件成立就不拼接 where
  • 使用起来非常简单,就是在if 标签集合外部套一个where标签
  • 仍然使用上一个案例:品牌、价格、汽车类型查询汽车数据

(1)接口中的方法

 /**
* 使用where标签,让我们的子句更加智能化
* @param brand
* @param guidePrice
* @param carType
* @return
*/
List<Car> selectByMultiConditionWithWhere(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType);

(2)映射文件中的SQL

<select id="selectByMultiConditionWithWhere" resultType="Car">
        select * from t_car
        <!--如果if标签没有成立的,就不会生成where关键字-->
        <where>
            <if test="brand != null and brand != ''">
                brand like "%"#{brand}"%"
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                guide_price > #{guidePrice}
            </if>
            <if test="carType != null and carType != ''">
                car_type = #{carType}
            </if>
        </where>
</select>

(3)测试类中的单元测试方法

@Test
public void testSelectByMultiConditionWithWhere(){
	SqlSession sqlSession = SqlSessionUtil.openSession();
	CarMapper mapper = sqlSession.getMapper(CarMapper.class);
	List<Car> cars = mapper.selectByMultiConditionWithWhere("", null, "");
	cars.forEach(car -> System.out.println(car));
	sqlSession.close();
}

实际生成的SQL语句如下,并且成功查询出所有的数据
在这里插入图片描述


四、trim 标签

  • trim 标签的优势是:动态的添加、删除前缀和后缀

  • 为什么需要这么做呢?

    • 上面if标签我们直接演示的是成功的案例,可能存在前面或后面有不应该出现的 andor
    • 我们可以动态的添加前缀和后缀,这个标签也是结合 if 标签使用的
  • trim 标签的组成:

    • prefix 属性:添加指定前缀
    • suffix 属性:添加指定后缀
    • prefixOverrides 属性:去除指定前缀
    • suffixOverrides 属性:去除指定后缀
  • 依旧采用根据品牌、价格、汽车类型筛选汽车数据

(1)接口方法:

/**
* 使用trim标签
* @param brand
* @param guidePrice
* @param carType
* @return
*/
List<Car> selectByMultiConditionWithTrim(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType);

(2)SQL 语句:

<select id="selectByMultiConditionWithTrim" resultType="Car">
        select * from t_car
        <trim prefix="where" suffixOverrides="and | or">
            <if test="brand != null and brand != ''">
                brand like "%"#{brand}"%" and
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                guide_price > #{guidePrice} or 
            </if>
            <if test="carType != null and carType != ''">
                car_type = #{carType} and
            </if>
        </trim>
</select>

(3)测试方法:【根据SQL和此处参数得知:要筛选大于55万的奔驰车或所有燃油车】

@Test
public void testSelectByMultiConditionWithTrim(){
	SqlSession sqlSession = SqlSessionUtil.openSession();
	CarMapper mapper = sqlSession.getMapper(CarMapper.class);
	List<Car> cars = mapper.selectByMultiConditionWithTrim("奔驰", 55.0, "燃油车");
	cars.forEach(car -> System.out.println(car));
	sqlSession.close();
}

测试结果:查询成功
在这里插入图片描述


五、Set 标签

  • 可以生成 set 关键字和去除末尾的 ,

  • 通过条件筛选,可以避免将字段更新为空值

  • 通常用于 update 语句,结合 if 标签使用

  • 接下来我们用 set 标签更新一条汽车信息

(1)接口方法:

 /**
* 更新汽车信息 -- set标签的使用
* @param car
* @return
*/
int updateBySet(Car car);

(2)SQL语句:

<update id="updateBySet">
        update t_car
        <!--通过指定更新的字段来避免更新空-->
        <set>
            <!--只有if语句成立的时候才会去更新对应的字段-->
            <if test="carNum != null and carNum != ''">car_num = #{carNum},</if>
            <if test="brand != null and brand != ''">brand = #{brand},</if>
            <if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},</if>
            <if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if>
            <if test="carType != null and carType != ''">car_type = #{carType}</if>
        </set>
</update>

(3)测试方法:

	@Test
    public void setUpdateBySet(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        mapper.updateById(new Car(2L, null, 75.0, null, null, ""));
        sqlSession.commit();
        sqlSession.close();
    }

(4)测试结果:我们指向更新id为2的汽车的价格,更新前
在这里插入图片描述
更新后:
在这里插入图片描述
在这里插入图片描述


六、choose when otherwise 标签

  • 这是类似于 if – else if – else 的语法 >> 最终只会选择一条子句拼接到SQL
  • 先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据汽车类型查询。【三者中选一个条件进行查询】

(1)接口方法:

/**
* 使用 choose when otherwise 标签
* @param brand
* @param guidePrice
* @param carType
* @return
*/
List<Car> selectByChoose(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType);

(2)SQL语句:

其实这里可以将where标签直接替换成where关键字,因为一定会拼接一个查询条件的【使用了otherwise标签】

<select id="selectByChoose" resultType="Car">
        select * from t_car
        <where>
            <choose>
                <when test="brand != null and brand != ''">
                    brand like "%"#{brand}"%"
                </when>
                <when test="guidePrice != null and guidePrice != ''">
                    guide_price > #{guidePrice}
                </when>
                <otherwise>
                    car_type = #{carType}
                </otherwise>
            </choose>
        </where>
</select>

(3)测试方法:

@Test
public void testSelectByChoose(){
	SqlSession sqlSession = SqlSessionUtil.openSession();
	CarMapper mapper = sqlSession.getMapper(CarMapper.class);
	List<Car> cars = mapper.selectByChoose("", 22.0, "电动车");
	cars.forEach(car -> System.out.println(car));
	sqlSession.commit();
	sqlSession.close();
}

(4)测试结果:查询成功
在这里插入图片描述


七、foreach 标签

  • 用于通过循环来完成某种操作,批量删除、批量添加
  • foreach 标签的组成:
    • collection 属性:传入的数组或集合
    • item 属性:数组或集合中的一个元素
    • separator 属性:分隔符
    • open 属性:foreach标签中所有内容的开始 “(”
    • close 属性:foreach标签中所有内容的结束 “)”

1、根据id组成的数组来完成批量删除

(1)接口方法

/**
* 批量删除
* @param ids 我们要删除的id数组
* @return 删除记录的条数
*/
int deleteByIds(@Param("ids") Long [] ids);

(2)SQL语句:

<delete id="deleteByIds">
        delete from t_car where id in(
        <foreach collection="ids" item="id" separator=",">
            <!--与item对应,代表我们从数组中取出的元素-->
            #{id}
        </foreach>
        )
</delete>

(3)测试方法:

@Test
    public void testDeleteByIds(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Long [] ids = {27L, 28L};
        int count = mapper.deleteByIds(ids);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
}

(4)测试结果:成功删除指定id的数据

2、根据传入的汽车数据集合批量插入
(1)接口方法

/**
* 批量插入,一次插入多条汽车信息
* @param cars 待插入的数据集合
* @return 插入成功的数据条数
*/
int insertBatch(@Param("ids") List<Car> cars);

(2)SQL语句:

<insert id="insertBatch">
        insert into t_car values
        <foreach collection="cars" item="car" separator=",">
            (null, #{car.carNum}, #{car.brand}, #{car.guidePrice}, #{car.produceTime}, #{car.carType})
        </foreach>
</insert>

(3)测试方法:

@Test
    public void testInsertBatch(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        // 创建我们的数据集合
        List<Car> cars = new ArrayList<>();
        cars.add(new Car(null, "100", "梅赛德斯", 66.0, "2022-11-07", "燃油车"));
        cars.add(new Car(null, "101", "奥迪A8", 67.0, "2022-11-07", "燃油车"));
        cars.add(new Car(null, "102", "宾利", 68.0, "2022-11-07", "燃油车"));
        // 调用我们的方法插入数据
        mapper.insertBatch(cars);
        // 提交事务、管理连接
        sqlSession.commit();
        sqlSession.close();
}

(4)测试结果:插入数据成功

在这里插入图片描述
在这里插入图片描述


八、sql 标签与 include 标签

  • 这两个标签一般配合使用,可以提高代码的复用率、易维护
  • 利用 sql 标签来声明sql片段, 它有个id属性标识唯一的sql
  • include标签可以导入sql片段在SQL语句中直接使用,使用refid属性指明用那个sql即可
<sql id="carCols">id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType</sql>

<select id="selectAllRetMap" resultType="map">
  select <include refid="carCols"/> from t_car
</select>

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

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

相关文章

Qt | QListView、QListWidget、QTableView、QTableWidget的使用示例及区别

Qt | QListView、QListWidget、QTableView、QTableWidget的使用示例及区别 目录Qt | QListView、QListWidget、QTableView、QTableWidget的使用示例及区别1、简介2、使用示例1、QListView2、QTableView3、QListWidget4、QTableWidget1、简介 QListView、QListWidget是列表形式…

Maven安装配置

Maven安装配置 第一步 : 解压 解压 apache-maven-3.6.1.rar 既安装完成 解压缩后的目录结构如下&#xff1a; bin目录 &#xff1a; 存放的是可执行命令。mvn 命令重点关注。conf目录 &#xff1a;存放Maven的配置文件。settings.xml 配置文件后期需要修改。lib目录 &#xf…

基于DPDK(x86平台)应用性能优化实践

产生性能瓶颈有多方面的原因&#xff0c;包括硬件&#xff08;自身能力限制或BIOS设置不当&#xff09;、操作系统&#xff08;某些feature没打开&#xff09;和软件。软件方面的性能瓶颈主要是由于编码不当导致&#xff0c;常见原因有以下几种&#xff1a; 数据结构cache lin…

【多线程】读写锁ReentrantReadWriteLock源码分析

【多线程】读写锁ReentrantReadWriteLock源码分析&#xff08;一&#xff09;读写锁ReentrantReadWriteLock源码分析【1】类图结构和参数【2】写锁的获取和释放&#xff08;1&#xff09;lock方法&#xff08;2&#xff09;lockInterruptibly方法&#xff08;3&#xff09;tryL…

GPS+北斗定位借助Arduino的数值显示

GPS北斗定位借助Arduino的数值显示 一、前言二、硬件要求三、参数基础四、原理剖析五、使用方式六、程序概要七、成果展示八、数据解析九、总结一、前言 较多的导航软件在生活中层出不穷&#xff0c;但是卫星定位同样也适用于轨迹记录、经纬分析、授时系统等&#xff0c;多样的…

【杰理AC696X】外挂FLASH音乐播放及Bin文件制作

外挂FLASH音乐播放及Bin文件制作 测试SDK版本&#xff1a;《ac696n_soundbox_sdk_v1.6.0》 文章目录外挂FLASH音乐播放及Bin文件制作前言一、板级配置1.1 SPI配置1.2 FLASH配置二、FLASH音乐播放测试三、FLASH BIN文件制作1.1 FLASHPCWinHex1.2 U盘分区工具WinHex1.3 FLASHPCF…

嵌入式单片机智能药盒设计(含代码)

目录 前言 设计的内容 &#xff08;1&#xff09;显示 &#xff08;2&#xff09;定时时间与用药量的设定 &#xff08;3&#xff09;实时时间调节 &#xff08;4&#xff09;报警功能 时钟模块 蓝牙模块 系统软件设计 系统主程序 按键函数 中断服务函数 作品展示 测试药…

2023年天津农学院专升本专业课参考教材

2023年天津农学院高职升本科专业课参考教材一、人力资源管理专业 1、《人力资源管理实用教程》 (第2版)&#xff0c;吴宝华&#xff0c;北京大学出版社 2、《人力资源管理》&#xff08;第4版&#xff09;&#xff0c;刘昕&#xff0c;中国人民大学出版社 3、《人力资源管理概论…

kobject 与sysfs属性文件读写

kobject和kset的简单总结 • kobject是struct kobject类型的对象。Kobject 有一个名字和一个引用计数。kobject 也有一个父指针&#xff08;允许 kobjects 被安排到层次结构中&#xff09;&#xff0c;一个特定的类型&#xff0c;也许还有一个在 sysfs 虚拟文件系统中的表示。…

OceanBase 4.0 解读:分布式查询性能提升,我们是如何思考的?

关于作者 王国平 OceanBase高级技术专家 目前OceanBase SQL引擎的技术负责人。2016年加入 OceanBase&#xff0c;负责SQL引擎的研发工作。2008年毕业于哈尔滨工业大学&#xff0c;2014年在新加坡国立大学获得博士学位&#xff0c;博士期间主要研究方向是数据库领域的(多)查询…

C++入门(2)-类与对象

类与对象初步认识类与对象一、面向过程与面向对象的区别二、类与结构体三、类的定义四、类的实例化五、类对象六、this指针七、构造函数八、析构函数九、拷贝构造函数十、运算符重载函数初步认识类与对象 一、面向过程与面向对象的区别 C语言是面向过程进行编程&#xff0c;注…

springboot整合其他项目

目录 一&#xff0c;集成Druid 学习地址&#xff1a; 主要讲监控 基于springboot视图渲染技术上增加代码 1.1 增加pom依赖 1.2 先在application.yml中添加Druid的数据源 1.3 其次在全局配置文件application.yml中添加所需的配置 配置截图&#xff1a; 配置解析 1.4 启动…

电脑录屏快捷键是什么?win10自带屏幕录制在哪

​在使用电脑的过程中&#xff0c;我们难免会遇到使用电脑录屏功能。有时候可能是想录制网课&#xff0c;有时候可能是想录制游戏的精彩操作&#xff0c;有时候可能只是想录制会议内容。 电脑录屏能够将重要的画面内容进行录制&#xff0c;十分的方便。但也有很多的小伙伴不清…

Python基础(三):PyCharm安装和使用

文章目录 PyCharm安装和使用 一、PyCharm的作用 二、PyCharm系统要求 三、下载和安装 四、PyCharm基本使用 五、PyCharm的基本设置 1、修改主题 2、修改代码文字格式 3、修改解释器 4、项目管理 PyCharm安装和使用 14天学习训练营导师课程&#xff1a;杨鑫《Python…

一、VSCode——免安装

介绍 Visual Studio Code支持可移植模式。此模式使 VS Code 创建和维护的所有数据都位于自身附近&#xff0c;因此可以跨环境移动。 此模式还提供了设置 VS Code 扩展的安装文件夹位置的方法&#xff0c;这对于阻止在 Windows AppData 文件夹中安装扩展的企业环境非常有用。 …

极市打榜|70G+已标注数据集出炉,油品泄露识别等全新算法上线!

极市打榜 算法打榜是极市平台推出的一种算法项目合作模式&#xff0c;至今已上线 100 产业端落地算法项目&#xff0c;已对接智慧城市、智慧工地、明厨亮灶等多个行业真实需求&#xff0c;算法方向涵盖目标检测、行为识别、图像分割、视频理解、目标跟踪、OCR等。 开发者报名…

CAN 协议控制器和物理总线之间的接口芯片SIT1040T 高速 CAN 总线收发器

CAN 协议控制器和物理总线之间的接口芯片SIT1040T 高速 CAN 总线收发器 CAN是最新进的现场总线,灵活性好,通讯可靠性高,抗干扰能力强&#xff0c;超长通信距离等优点,110个节点,兼带CAN-FD功能产品,容错电压可达-70V~ 70V,温度范围高达-40C ~ 150C最初应用于汽车电子,目前已广…

安信可Ai-WB1系列AT指令连接MQTT阿里云物联网平台

文章目录前言1 准备材料2 创建云端设备3 硬件连接4 配置终端设备5 MQTT实现发布&订阅消息联系我们前言 本文将介绍安信可AI-WB1系列通过AT指令接入阿里云物联网平台&#xff0c;实现MQTT的订阅和发布。 1 准备材料 AI-WB1系列模组或者开发板USB转TTL模块/Type-C数据线阿…

数仓建设教程

50000字&#xff0c;数仓建设保姆级教程&#xff0c;离线和实时一网打尽(理论实战) 上 - 腾讯云开发者社区-腾讯云 (tencent.com)50000字&#xff0c;数仓建设保姆级教程&#xff0c;离线和实时一网打尽(理论实战) 下_五分钟学大数据的技术博客_51CTO博客#yyds干货盘点#最强最全…

什么是DDoS攻击?企业服务器是否需要DDoS防御

有时候你可能会遇到某个网站突然打不开&#xff0c;这一段时间后发布自己被DDos攻击的公告&#xff0c; 那么&#xff0c;为什么DDOS攻击能让服务器瘫痪&#xff1f;黑客又如何执行DDos攻击的呢&#xff1f; DDoS全称为Distributed Denial of Service&#xff08;分布式拒绝服…