多数据源组件dynamic-datasource使用总结

简介

dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。

其支持 Jdk 1.7+, SpringBoot 1.5.x 2.x.x 3.x.x

特性

  • 支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。
  • 支持数据库敏感配置信息 加密(可自定义) ENC()。
  • 支持每个数据库独立初始化表结构schema和数据库database。
  • 支持无数据源启动,支持懒加载数据源(需要的时候再创建连接)。
  • 支持 自定义注解 ,需继承DS(3.2.0+)。
  • 提供并简化对Druid,HikariCp,BeeCp,Dbcp2的快速集成。
  • 提供对Mybatis-Plus,Quartz,ShardingJdbc,P6sy,Jndi等组件的集成方案。
  • 提供 自定义数据源来源 方案(如全从数据库加载)。
  • 提供项目启动后 动态增加移除数据源 方案。
  • 提供Mybatis环境下的 纯读写分离 方案。
  • 提供使用 spel动态参数 解析数据源方案。内置spel,session,header,支持自定义。
  • 支持 多层数据源嵌套切换 。(ServiceA >>> ServiceB >>> ServiceC)。
  • 提供 基于seata的分布式事务方案 。
  • 提供 本地多数据源事务方案。

快速入门 

第一步:pom.xml  引入dynamic-datasource-spring-boot-starter、

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

第二步:application.yml 配置多数据源

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://192.168.43.10:3306/bill?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&autoReconnect=true
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://192.168.43.10:3306/usc?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&autoReconnect=true
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver

第三步:使用@DS注解,切换数据源

@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解

注解结果
没有@DS默认数据源
@DS("dsName")dsName可以为组名也可以为具体某个库的名称

连接池集成 

在application.yml 配置文件中添加Hikari数据库连接池配置。

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://192.168.43.10:3306/bill?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&autoReconnect=true
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://192.168.43.10:3306/usc?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&autoReconnect=true
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
      hikari:
        minimum-idle: 10
        maximum-pool-size: 20
        idle-timeout: 500000
        max-lifetime: 540000
        connection-timeout: 60000
        connection-test-query: select 1

dynamic-datasource 支持如下数据库连接池:beecp\dbcp2\druid\hikair 等常用数据库连接池。

Beecp 通用配置:

beecp:
      fairness: true
      initial-size: 5
      max-active: 20
      idleTimeout: 60000
      connectionTestSql: SELECT 1

dbcp2 通用配置:

dbcp2:
    initial-size:5
    min-idle:5
    max-idle:10
    max-open-prepared-statements:100

druid 通用配置:

druid:
      # 初始化大小
      initial-size: 5
      # 最小连接数
      min-idle: 10
      # 最大连接数
      max-active: 20
      # 获取连接时的最大等待时间
      max-wait: 60000
      # 一个连接在池中最小生存的时间,单位是毫秒
      min-evictable-idle-time-millis: 300000
      # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
      time-between-eviction-runs-millis: 60000
      # 配置扩展插件:stat-监控统计,log4j-日志,wall-防火墙(防止SQL注入),去掉后,监控界面的sql无法统计
      filters: stat,wall
      # 检测连接是否有效的 SQL语句,为空时以下三个配置均无效
      validation-query: SELECT 1
      # 申请连接时执行validationQuery检测连接是否有效,默认true,开启后会降低性能
      test-on-borrow: true
      # 归还连接时执行validationQuery检测连接是否有效,默认false,开启后会降低性能
      test-on-return: true
      # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效,默认false,建议开启,不影响性能
      test-while-idle: true
      # 是否开启 StatViewServlet
      stat-view-servlet:
        enabled: true
        # 访问监控页面 白名单,默认127.0.0.1
        allow: 127.0.0.1
        login-username: admin
        login-password: admin
      # FilterStat
      filter:
        stat:
          # 是否开启 FilterStat,默认true
          enabled: true
          # 是否开启 慢SQL 记录,默认false
          log-slow-sql: true
          # 慢 SQL 的标准,默认 3000,单位:毫秒
          slow-sql-millis: 5000
          # 合并多个连接池的监控数据,默认false
          merge-sql: false

hikair 通用配置:

 hikari:
        minimum-idle: 10
        maximum-pool-size: 20
        idle-timeout: 500000
        max-lifetime: 540000
        connection-timeout: 60000
        connection-test-query: select 1

温馨提示:上述配置对象属性值与 dynamic-datasource定义的属性值对象可能存在差异,请以:

com.baomidou.dynamic.datasource.spring.boot.autoconfigure.* 相关配置类对象为主 

验证 dynamic-datasource 数据库连接池是否生效。

在任意类中依赖DataSource 接口类,检查输出的接口实例类是否为:com.baomidou.dynamic.datasource.DynamicRoutingDataSource。

示例代码:

package com.zzg.controller;


import com.zzg.entity.BaseProjectPO;
import com.zzg.service.IBaseProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.sql.DataSource;
import java.util.List;

@RestController
@RequestMapping("/baseProject")
public class BaseProjectController {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private IBaseProjectService service;

    @GetMapping("/list")
    public List<BaseProjectPO> list() {
        System.out.println(dataSource.getClass());
        return service.list();
    }

    @GetMapping("{id}")
    public BaseProjectPO getBaseProjectInfo(@PathVariable String id){
        return service.getById(id);
    }
}

在list 逻辑方法中,输出DataSource 接口实例对象为:com.baomidou.dynamic.datasource.DynamicRoutingDataSource

第三方集成 /MyBatis-plus

在application.yml 和Application 程序入口添加如下配置:

application.yml

mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: cn.zzg.entity
Application
package com.zzg;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan({"com.zzg.mapper"})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

进阶使用

动态添加和移除数据源

示例:

1、定义数据源Model

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class DataSourceDTO {
    @NotBlank
    @ApiModelProperty(value = "连接池名称", example = "db1")
    private String poolName;
    @NotBlank
    @ApiModelProperty(value = "JDBC driver", example = "com.mysql.cj.jdbc.Driver")
    private String driverClassName;
    @NotBlank
    @ApiModelProperty(value = "JDBC url 地址", example = "jdbc:mysql://x.x.x.x:3306/x?useUnicode=true&characterEncoding=utf-8")
    private String url;
    @NotBlank
    @ApiModelProperty(value = "JDBC 用户名", example = "sa")
    private String username;
    @ApiModelProperty(value = "JDBC 密码")
    private String password;
}

2、Controller 定义添加和移除数据源

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.*;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.zzg.common.DataSourceDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
 
import javax.sql.DataSource;
import java.util.Set;
 
@RestController
@RequestMapping("/datasources")
@Api(tags = "添加删除数据源")
public class DataSourceController {
 
    @Autowired
    private DataSource dataSource;
    @Autowired
    private DefaultDataSourceCreator dataSourceCreator;
    @Autowired
    private DruidDataSourceCreator druidDataSourceCreator;
    @Autowired
    private HikariDataSourceCreator hikariDataSourceCreator;
 
    @GetMapping
    @ApiOperation("获取当前所有数据源")
    public Set<String> now() {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        return ds.getDataSources().keySet();
    }
 
    //通用数据源会根据maven中配置的连接池根据顺序依次选择。
    //默认的顺序为druid>hikaricp>beecp>dbcp>spring basic
    @PostMapping("/add")
    @ApiOperation("通用添加数据源(推荐)")
    public Set<String> add(@Validated @RequestBody DataSourceDTO dto) {
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        BeanUtils.copyProperties(dto, dataSourceProperty);
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
        ds.addDataSource(dto.getPoolName(), dataSource);
        return ds.getDataSources().keySet();
    }
 
    @PostMapping("/addDruid")
    @ApiOperation("基础Druid数据源")
    public Set<String> addDruid(@Validated @RequestBody DataSourceDTO dto) {
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        BeanUtils.copyProperties(dto, dataSourceProperty);
        dataSourceProperty.setLazy(true);
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        DataSource dataSource = druidDataSourceCreator.createDataSource(dataSourceProperty);
        ds.addDataSource(dto.getPoolName(), dataSource);
        return ds.getDataSources().keySet();
    }
 
    @PostMapping("/addHikariCP")
    @ApiOperation("基础HikariCP数据源")
    public Set<String> addHikariCP(@Validated @RequestBody DataSourceDTO dto) {
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        BeanUtils.copyProperties(dto, dataSourceProperty);
        dataSourceProperty.setLazy(true);//3.4.0版本以下如果有此属性,需手动设置,不然会空指针。
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
        ds.addDataSource(dto.getPoolName(), dataSource);
        return ds.getDataSources().keySet();
    }
 
    @DeleteMapping
    @ApiOperation("删除数据源")
    public String remove(String name) {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        ds.removeDataSource(name);
        return "删除成功";
    }
}

数据库加密

第一步:使用框架自带加密工具类com.baomidou.dynamic.datasource.toolkit.CryptoUtils对需要加密的字符串进行加密。

@Test
void test() throws Exception {
    String passWord= CryptoUtils.encrypt("123456");
    System.out.println(passWord);
    // 输出加密密码
 //Y3ycHCcZGa+N+OK+qXTWA0gJ1L1N+FYrswTgRQEegdKVTefiujYxjlytR6zOuV5Y3AifL/P10yWshYKQaqpkkQ==
}

第二步:修改配置文件中的相关密码

server:
  port: 8080
spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://192.168.43.10:3306/bill?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&autoReconnect=true
          username: root
          password: ENC(Y3ycHCcZGa+N+OK+qXTWA0gJ1L1N+FYrswTgRQEegdKVTefiujYxjlytR6zOuV5Y3AifL/P10yWshYKQaqpkkQ==)
          driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://192.168.43.10:3306/usc?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&autoReconnect=true
          username: root
          password: ENC(Y3ycHCcZGa+N+OK+qXTWA0gJ1L1N+FYrswTgRQEegdKVTefiujYxjlytR6zOuV5Y3AifL/P10yWshYKQaqpkkQ==)
          driver-class-name: com.mysql.cj.jdbc.Driver
      hikari:
        minimum-idle: 10
        maximum-pool-size: 20
        idle-timeout: 500000
        max-lifetime: 540000
        connection-timeout: 60000
        connection-test-query: select 1
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: cn.zzg.entity

自动读写分离

通过上面的学习,我们已经学习了解到了@DS 注解,基于此注解我们可以快速实现简单版本的读写分离。

package com.zzg.mapper;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zzg.entity.BaseArch;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface BaseArchMapper extends BaseMapper<BaseArch> {

    @DS("master")
    int addUser(BaseArch entity);

    @DS("slave_1")
    BaseArch findUser(@Param("id") String id);
}

不过这种方式有点繁琐,每个Mapper都需要添加注解。我们 可以通过MyBatis 拦截器 + 手动切换数据源实现读写分离。

定义:读写分离MyBatis 拦截器

@Intercepts({@Signature(
        type = Executor.class,
        method = "query",
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
), @Signature(
        type = Executor.class,
        method = "query",
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}
), @Signature(
        type = Executor.class,
        method = "update",
        args = {MappedStatement.class, Object.class}
)})
@Component
@Primary
public class MasterSlaveAutoRoutingPlugin implements Interceptor {

    private static final String MASTER = "master";

    private static final String SLAVE = "slave_1";

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        try {
            DynamicDataSourceContextHolder.push(SqlCommandType.SELECT == ms.getSqlCommandType() ? SLAVE : MASTER);
            return invocation.proceed();
        } finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    @Override
    public Object plugin(Object target) {
        return target instanceof Executor ? Plugin.wrap(target, this) : target;
    }

    @Override
    public void setProperties(Properties properties) {
    }
}

至此,我们可以移除Controller/Service/Dao/Mapper 上得@DS 注解。

手动切换数据源

请参考文章:多数据源切换[dynamic-datasource] 手动切换数据源

负载均衡 

通过 mybatis 的拦截器 + 手动切换数据源实现了读写分离,同时 dynamic-datasource 还为我们提供了负载的效果,同一个组下的默认就是负载均衡效果,怎么才是同一个组呢,上面有提到只需以下划线 _ 分割即可,下面修改配置文件:

spring:
  datasource:
    dynamic:
      primary: db_1 #设置默认的数据源或者数据源组,默认值即为master
      strict: true #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源.
      datasource:
        db_1:
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.alibaba.druid.pool.DruidDataSource
          url: jdbc:mysql://192.168.43.10:3306/db1?useUnicode=true&characterEncoding=utf8
          username: root
          password: 123456
        db_2:
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.alibaba.druid.pool.DruidDataSource
          url: jdbc:mysql://192.168.43.10:3306/db2?useUnicode=true&characterEncoding=utf8
          username: root
          password: 123456

声明 Dao ,指定数据源为 db :

@Mapper
@DS("db")
public interface UserMapper extends BaseMapper<UserEntity> {
}

 事务管理

大家都了解在 Spring 中事物使用 @Transactional 注解即可,但是仅针对于单个数据源的情况,多数据源下我们可以使用 jta 来控制或其他事务管理框架,在 dynamic-datasource 中又推出了 @DSTransactional 注解来代替 Spring 的 @Transactional 注解。

@Slf4j
@SpringBootTest
class DynamicDatasourceDemoApplicationTests {

    @Autowired
    DB1UserDao db1UserDao;

    @Autowired
    DB2UserDao db2UserDao;

    @Test
    @DSTransactional
    void test1() {
        UserEntity entity = new UserEntity();
        entity.setName("王五");
        entity.setAge(16);
        int db1 = db1UserDao.insert(entity);
        log.info("db1写入个数:{} ", db1);
        int db2 = db2UserDao.insert(entity);
        log.info("db2写入个数:{} ", db2);
        //模拟异常
        int a = 1 / 0;
    }
}

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

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

相关文章

matlab基本操作

目录 1 清空workspace 2 清空命令行窗口 3 求字符的ASCII码 4 矩阵的表示 5 矩阵的转置 6 按列输出 7 求逆矩阵 8 创建零矩阵 9 生成随机数 10 生成空数组 11 生成单位矩阵 12 生成幻方矩阵 13 结构体 14 重复 15 点乘与叉乘 16 寻找符合条件的元素…

Hadoop, HIve, Spark关系简述

大数据∈数据管理系统的范畴 数据管理系统&#xff1a; 数据怎么存&#xff1f;数据怎么算&#xff1f; 单机数据管理时代下&#xff0c; 数据处理的任务&#xff1a;IO密集型&#xff1b; 数据存不下&#xff1f; HDFS用于存放多机器的数据并提供相关Api接口。 HDFS中引入了…

146基于matlab的齿轮非线性动力学

基于matlab的齿轮非线性动力学&#xff0c;绘出系统状态变量随参数变化分岔图&#xff0c;绘图参数对应的系统各周期及混沌状态的时间历程图、相轨迹图、Poincare映射图&#xff0c;程序已调通&#xff0c;可直接运行。 146 matlab 齿轮非线性动力学 相图 (xiaohongshu.com)

【前端web入门第二天】01 html语法实现列表与表格_合并单元格

html语法实现列表与表格 文章目录: 1.列表 1.1 无序列表1.2 有序列表1.3 定义列表 2.表格 2.1 表格基本结构2.2 表格结构标签2.3 合并单元格 写在最前,第二天学习目标: 列表 表格 表单 元素为嵌套关系 1.列表 作用:布局内容排列整齐的区域。 列表分类:无序列表、有序列表…

【leetcode题解C++】101.对称二叉树 and 111.二叉树的最小深度 and 222.完全二叉树的节点个数 and 110.平衡二叉树

101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 思路&#xff1a…

2023启示录|虚拟人这一年

图片&#xff5c;《银翼杀手 2049》剧照 作者丨程心 编辑丨罗辑 2023 年&#xff0c;大模型 “救活” 了很多行业&#xff0c;其中最为反转的&#xff0c;就是把虚拟数字人&#xff08;以下简称虚拟人&#xff09;从活死人墓里拉了出来。 还没开年&#xff0c;在 2022 年火…

python_ACM模式《剑指offer刷题》链表3

题目&#xff1a; 注意&#xff1a; 剑指offer上对这道题目的描述是给定的删除节点是节点指针。这表明这道题可以用时间复杂度为O(1)的方式解决。 而leetcode上对类似本题的描述是&#xff1a; 给定删除节点是节点值&#xff0c;这决定了本题时间复杂度必然至少为O(N)。因为…

PINN物理信息网络 | 全局自适应物理信息神经网络SA-PINN

概述 本文提出的自适应加权方法在于权重适用于不同损失组件中的个别训练点,而不是整个损失组件。之前的方法可以被看作是这个方法的一个特例,当所有针对特定损失组件的自适应权重同时更新时。在之前的方法中,独立开发的极小极大加权方案[16]与SA-PINNs最为相近,因为它也通过…

SpringCloud--FeignGateWay

Feign 创建项目勾选web SpringWeb 1.0 创建生产者SpringCloudFeignProvider 端口号:8081 pom.xml引入依赖 <!--nacos依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery<…

语义分割(3):损失函数解析

文章目录 1. 常见语义分割损失1.1 Cross Entropy1.2 dice Loss1.2.1 为什么使用Dice loss1.2.2 公式1.2.3 Dice loss 和 F1-score代码 1.3 focal loss1.3.1 公式&#xff1a;1.3.2 代码 2. 语义分割损失应用参考 语义分割任务实际上是一种像素层面上的分类&#xff0c;需要识别…

回归预测 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多输入单输出回归预测

回归预测 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多输入单输出回归预测 目录 回归预测 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多输入单输出回归预测预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab基于SSA-SVR麻雀算法优化支持向量机的数据…

Qlik Sense 使用Join合并表格

Join | Windows 版 Qlik Sense帮助 什么是Qlik Sense的Join join 前缀可连接加载的表格和现有已命名的表格或最近创建的数据表。本质上跟SQL的Join很类似。 联接数据的效果是通过一组额外的字段或属性扩展目标表&#xff0c;即目标表中不存在的字段或特性。源数据集和目标表之间…

牛客——只能吃土豆的牛牛(进制转化)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 旅行完了的牛牛又胖了&#xff0c;于是他终于下决心要戒掉零食&#xff0c;所以他带着他最爱的土豆回到了牛星&#xff0c;开始了在牛星种土豆和只吃土豆减肥的日子。&#xff08;吃土豆能减肥…

Future模式先给您提货单

Future模式是一种设计模式&#xff0c;用于在处理耗时操作时提高程序的响应性。 角色介绍: Main类: 负责向Host发出请求并获取数据的类。 Host类: 负责向请求返回FutureData的实例的类&#xff0c;起到调度的作用。 Data接口: 表示访问数据的方法的接口&#xff0c;由FutureD…

S275智慧煤矿4G物联网网关:矿山开采的未来已来

随着经济发展煤矿需求不断激增&#xff0c;矿山矿井普遍处于偏远山区&#xff0c;生产管理、人员安全、生产效率是每个矿山矿井都需要考虑的问题&#xff0c;利用网关对现场终端设备连接组网&#xff0c;实现智慧煤矿远程管理。 各矿山矿井分布范围比较广泛&#xff0c;户外环…

python内置函数有哪些?整理到了7大分类48个函数,都是工作中常用的函数

python内置函数 一、入门函数 1.input() 功能&#xff1a; 接受标准输入&#xff0c;返回字符串类型 语法格式&#xff1a; input([提示信息])实例&#xff1a; # input 函数介绍text input("请输入信息:") print("收到的数据是:%s" % (text))#输出…

Qt Design Studio+Pyside项目

Qt Design Studio设计出的项目结构有多个层级的目录&#xff0c;我们直接用类似Qt Creator工具的方式加载main.qml文件时会报错提示module "content" is not installed&#xff0c;将content加入importPath后还是报同样的错误。 Qt Design Studio生成的文件包含了.qm…

lv14 内核内存管理、动态分频及IO访问 12

一、内核内存管理框架 内核将物理内存等分成N块4KB&#xff0c;称之为一页&#xff0c;每页都用一个struct page来表示&#xff0c;采用伙伴关系算法维护 补充&#xff1a; Linux内存管理采用了虚拟内存机制&#xff0c;这个机制可以在内存有限的情况下提供更多可用的内存空…

路由、组件目录存放

文章目录 单页应用程序&#xff1a;SPA- Single Page Application路由的介绍VuePouter的介绍VueRouted 的使用 组件目录存放问题&#xff08;组件分类&#xff09; 单页应用程序&#xff1a;SPA- Single Page Application 单页应用&#xff08;SPA&#xff09;:所有功能在一个…

Springmvc-@RequestBody

SpringBoot-2.7.12 请求的body参数无法转换&#xff0c;服务端没有报错信息打印&#xff0c;而是响应的状态码是400 PostMapping("/static/user") public User userInfo(RequestBody(required false) User user){user.setAge(19);return user; }PostMapping("…