当前位置: 首页 > news >正文

《手写Spring渐进式源码实践》实践笔记 (第二十一章 将ORM框架整合到Spring容器中)

文章目录

  • 第二十一章 ORM框架整合Spring
    • 背景
    • 目标
    • 设计
    • 实现
      • 代码结构
      • 类图
      • 实现步骤
    • 测试
      • 事先准备
      • 属性配置文件
      • 测试用例
      • 测试结果:
    • 总结

第二十一章 ORM框架整合Spring

背景

MyBatis-Spring 能够实现 MyBatis 与 Spring 框架的无缝集成。它使得 MyBatis 能够参与 Spring 的事务管理,自动创建 Mapper 和 SqlSession 并将其注册为 Spring 容器中的 Bean,同时将 MyBatis 的异常转换为 Spring 的 DataAccessException。这样,应用程序的代码就可以不依赖于 MyBatis、Spring 或 MyBatis-Spring,实现解耦。

目标

基于当前实现的 Spring 框架,和简易的mybatis orm框架,实现两者的结合,完成mybatis-spring的功能封装。

设计

MyBatis-Spring 将 MyBatis 的功能与 Spring 框架的依赖注入和事务管理无缝集成,通过接口和抽象层进行交互,通过自动配置功能,可以自动创建 SqlSession 和 Mapper 接口的实现,并将其注册为 Spring Bean,从而简化了配置过程。整体设计结构如下图:

image-20241202112523377

实现

代码结构

image-20241120183420684

源码实现:https://github.com/swg209/spring-study/tree/main/step21-spring-mybatis

类图

image-20241120183448881

在整个类图中,通过在spring.xml配置自动注册、加载MapperScannerConfigure Bean,调用扫描方法,自动将指定文件路径下的mapper进行解析成MapperFactoryBean,注册对应的接口方法和sqlSessionFactory。

实现步骤

  1. step21的代码module的最外层pom 引入step-20 orm简易框架实现模块

     <dependency><groupId>cn.suwg.springframework</groupId><artifactId>step20-simple-orm</artifactId><version>1.0-SNAPSHOT</version></dependency>
    
  2. 定义SqlSessionFactoryBean

    定义SqlSessionFactoryBean, 实现了 FactoryBean, InitializingBean,处理mybatis核心流程类加载处理,通过SqlSessionFactoryBuilder使用ORM框架

    public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean {// 资源路径private String resource;private SqlSessionFactory sqlSessionFactory;@Overridepublic SqlSessionFactory getObject() throws Exception {return sqlSessionFactory;}@Overridepublic Class<?> getObjectType() {return sqlSessionFactory.getClass();}@Overridepublic boolean isSingleton() {return true;}@Overridepublic void afterPropertiesSet() throws BeansException {DefaultResourceLoader defaultResourceLoader = new DefaultResourceLoader();Resource resource = defaultResourceLoader.getResource(this.resource);try (InputStream inputStream = resource.getInputStream()) {//根据mapper文件,创建对应的sql会话工厂.this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);} catch (Exception e) {e.printStackTrace();}}public void setResource(String resource) {this.resource = resource;}
    }
    
  3. 定义MapperFactoryBean,完成代理类的实现, 完成对 SQL 的所有操作的分发处理。

    • T getObject(),中是一个 Java 代理类的实现,这个代理类对象会被挂到你的注入中。真正调用方法内容时会执行到代理类的实现部分,对应测试例子中,打印日志“你被代理了,执行SQL操作!

    • InvocationHandler,代理类的实现,主要开启SqlSession,并通过固定key执行结果,查询到结果信息会反射操作成对象类,这里就是我们实现的 ORM 中间件负责的事情了。

      public class MapperFactoryBean<T> implements FactoryBean<T> {private Class<T> mapperInterface;private SqlSessionFactory sqlSessionFactory;public MapperFactoryBean() {}public MapperFactoryBean(Class<T> mapperInterface, SqlSessionFactory sqlSessionFactory) {this.mapperInterface = mapperInterface;this.sqlSessionFactory = sqlSessionFactory;}@Overridepublic T getObject() throws Exception {InvocationHandler handler = ((proxy, method, args) -> {// 排除 Object 方法;toString、hashCodeif (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);}try {System.out.println("你被代理了,执行SQL操作!" + method.getName());return sqlSessionFactory.openSession().selectOne(mapperInterface.getName() + "." + method.getName(), args[0]);} catch (Exception e) {e.printStackTrace();}return method.getReturnType().newInstance();});return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{mapperInterface}, handler);}@Overridepublic Class<?> getObjectType() {return mapperInterface;}@Overridepublic boolean isSingleton() {return true;}public Class<T> getMapperInterface() {return mapperInterface;}public void setMapperInterface(Class<T> mapperInterface) {this.mapperInterface = mapperInterface;}public SqlSessionFactory getSqlSessionFactory() {return sqlSessionFactory;}public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}
      }
  4. 定义MapperScannerConfigure,完成注册对象的扫描, 代理类的Bean注册.

    • 把 DAO 接口全部扫描出来,完成代理和注册到 Spring Bean 容器。
    • 表、类的扫描注册,classpath:org/suwg/demo/dao/**/.class,解析class文件获取资源信息; Set<Class<?>> classes = ClassScanner.scanPackage(basePackage);
    • 遍历 Resource,获取class 信息,用于注册 bean。
    • 最后执行注册 registry.registerBeanDefinition(clazz.getSimpleName(), beanDefinition);
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor {private String basePackage;private SqlSessionFactory sqlSessionFactory;@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {try {// 类的扫描Set<Class<?>> classes = ClassScanner.scanPackage(basePackage);for (Class<?> clazz : classes) {// Bean 对象定义BeanDefinition beanDefinition = new BeanDefinition(clazz);PropertyValues propertyValues = new PropertyValues();propertyValues.addPropertyValue(new PropertyValue("mapperInterface", clazz));propertyValues.addPropertyValue(new PropertyValue("sqlSessionFactory", sqlSessionFactory));beanDefinition.setPropertyValues(propertyValues);beanDefinition.setBeanClass(MapperFactoryBean.class);// Bean 对象注册registry.registerBeanDefinition(clazz.getSimpleName(), beanDefinition);}} catch (Exception e) {e.printStackTrace();}}public void setBasePackage(String basePackage) {this.basePackage = basePackage;}public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}
}

测试

事先准备

步骤1: 新建my_user表,往表里插入几条数据.

-- mybatis.my_user definitionCREATE TABLE `my_user` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增ID',`user_id` varchar(9) DEFAULT NULL COMMENT '用户ID',`user_head` varchar(16) DEFAULT NULL COMMENT '用户头像',`create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间',`update_time` timestamp NULL DEFAULT NULL COMMENT '更新时间',`user_name` varchar(64) DEFAULT NULL COMMENT '用户名',`user_password` varchar(64) DEFAULT NULL COMMENT '用户密码',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;INSERT INTO mybatis.my_user (user_id, user_head, create_time, update_time, user_name, user_password) VALUES
('1', '头像', '2024-03-25 18:00:12', '2024-03-25 18:00:12', '小苏', 's123asd'),
('2', '头像', '2024-03-25 18:00:12', '2024-03-25 18:00:12', '小苏', 's123asd');

步骤2: 创建用户类User ,Dao接口类 IUserDao

public class User {private Long id;private String userId;          // 用户IDprivate String userName;    // 昵称private String userHead;        // 头像private String userPassword;    // 密码private Date createTime;        // 创建时间private Date updateTime;        // 更新时间public User() {}public User(String userName) {this.userName = userName;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getUserName() {return userName;}public void setUserName(String userNickName) {this.userName = userNickName;}public String getUserHead() {return userHead;}public void setUserHead(String userHead) {this.userHead = userHead;}public String getUserPassword() {return userPassword;}public void setUserPassword(String userPassword) {this.userPassword = userPassword;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}}

IUserDao

public interface IUserDao {User queryUserInfoById(Long id);List<User> queryUserList(User user);}

属性配置文件

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="sqlSessionFactory" class="cn.suwg.springframework.mybatis.SqlSessionFactoryBean"><property name="resource" value="classpath:mybatis-config-datasource.xml"/></bean><bean class="cn.suwg.springframework.mybatis.MapperScannerConfigurer"><!-- 注入sqlSessionFactory --><property name="sqlSessionFactory" ref="sqlSessionFactory"/><!-- 给出需要扫描Dao接口包 --><property name="basePackage" value="cn.suwg.springframework.mybatis.test.dao"/></bean></beans>

数据库配置 mybatis-config-datasource.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><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><mapper resource="mapper/User_Mapper.xml"/></mappers></configuration>

User_Mapper.xml

<?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="cn.suwg.springframework.mybatis.test.dao.IUserDao"><select id="queryUserInfoById" parameterType="java.lang.Long"resultType="cn.suwg.springframework.mybatis.test.po.User">SELECT id, user_id, user_name, user_head, user_password, create_timeFROM my_userwhere id = #{id}</select><select id="queryUserList" parameterType="cn.suwg.springframework.mybatis.test.po.User"resultType="cn.suwg.springframework.mybatis.test.po.User">SELECT id, user_id, user_name, user_head, user_password, create_time, update_timeFROM my_userwhere user_name = #{userName}</select></mapper>

测试用例

public class ApiTest {@Testpublic void testClassPathXmlApplicationContext() {BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:spring.xml");IUserDao userDao = beanFactory.getBean("IUserDao", IUserDao.class);User user = userDao.queryUserInfoById(1L);System.out.println("测试结果:" + JSON.toJSONString(user));}
}

测试结果:

image-20241202193159041

  • 从测试结果中可以看到,可以正常调用orm框架,与数据库交互,查询表数据功能。

总结

  • 本章节成功实现了MyBatis与Spring的整合,提供了一个简化配置、自动管理事务和异常处理的框架,使得开发者可以更专注于业务逻辑的实现。通过自动配置和代理机制,MyBatis-Spring框架简化了MyBatis与Spring的集成过程,提高了开发效率和代码的可维护性。

参考书籍:《手写Spring渐进式源码实践》

书籍源代码:https://github.com/fuzhengwei/small-spring

相关文章:

《手写Spring渐进式源码实践》实践笔记 (第二十一章 将ORM框架整合到Spring容器中)

文章目录 第二十一章 ORM框架整合Spring背景目标设计实现代码结构类图实现步骤 测试事先准备属性配置文件测试用例测试结果&#xff1a; 总结 第二十一章 ORM框架整合Spring 背景 MyBatis-Spring 能够实现 MyBatis 与 Spring 框架的无缝集成。它使得 MyBatis 能够参与 Spring…...

数据库管理-第267期 23ai:Oracle Data Redaction演示(20241128)

数据库管理267期 2024-11-286 数据库管理-第267期 23ai&#xff1a;Oracle Data Redaction演示&#xff08;20241128&#xff09;1 示例表及数据2 创建编校策略2.1 名字全编校2.2 电话部分编校 3 DML演示3.1 场景13.2 场景2 总结 数据库管理-第267期 23ai&#xff1a;Oracle Da…...

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测,含优化前后对比

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测&#xff0c;含优化前后对比 目录 NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测&#xff0c;含优化前后对比预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介…...

第六届国际科技创新学术交流会暨管理科学信息化与经济创新发展(MSIEID 2024)

重要信息 大会官网&#xff1a;msieid2024.iaecst.org &#xff08;点击了解大会&#xff0c;参会等内容&#xff09; 大会时间&#xff1a;2024年12月6-8日 大会地点&#xff1a;中国-广州 大会简介 随着全球化和信息化的不断深入&#xff0c;管理科学、信息化和经济发展…...

【计算机视觉算法与应用】模板匹配、图像配准

目录 1. 基于灰度值的模板匹配 2. 基于相关性的模板匹配 3. 基于形状的模板匹配 4. 基于组件的模板识别 5. 基于形变的模板匹配 6. 基于描述符的模板匹配 7. 基于点的模板匹配 性能比较 模板匹配的算法实现需要结合具体需求和应用场景来选择方法。以下是基于 OpenCV 的…...

HHO-CNN-BiGRU-Attention哈里斯鹰优化算法卷积神经网络结合双向门控循环单元时间序列预测,含优化前后对比

HHO-CNN-BiGRU-Attention哈里斯鹰优化算法卷积神经网络结合双向门控循环单元时间序列预测&#xff0c;含优化前后对比 目录 HHO-CNN-BiGRU-Attention哈里斯鹰优化算法卷积神经网络结合双向门控循环单元时间序列预测&#xff0c;含优化前后对比预测效果基本介绍模型描述程序设计…...

数据并行、模型并行与张量并行:深度学习中的并行计算策略(中英双语)

中文版 数据并行、模型并行与张量并行&#xff1a;深度学习中的并行计算策略 随着深度学习模型的不断增大&#xff0c;单个计算节点&#xff08;例如单个 GPU&#xff09;的计算和内存能力逐渐成为了限制训练效率和模型规模的瓶颈。为了应对这些挑战&#xff0c;深度学习社区…...

大数据-239 离线数仓 - 广告业务 测试 FlumeAgent 加载ODS、DWD层

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…...

Python中的数据结构深入解析:从列表到字典的优化技巧

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! Python是一门以易用性和可读性著称的高级编程语言,其内置的数据结构为开发者提供了强大的工具,但了解其底层实现及性能优化策略却常被忽略。本文深入探讨Python中的核心数据结构,包括列表(list)、元组…...

【JS】JS判断数据类型

typeof // typeof 后面括号有没有都可以 console.log(typeof(a)) // string console.log(typeof(123)) // number console.log(typeof(undefined)) // undefined console.log(typeof(true)) // boolean console.log(typeof(Symbol(123))) // symbolconsole.log(typeof(null)) /…...

基于jmeter+perfmon的稳定性测试记录

软件测试资料领取&#xff1a;[内部资源] 想拿年薪40W的软件测试人员&#xff0c;这份资料必须领取~ 软件测试面试刷题工具领取&#xff1a;软件测试面试刷题【800道面试题答案免费刷】 1. 引子 最近承接了项目中一些性能测试的任务&#xff0c;因此决定记录一下&#xff0c…...

【0351】Postgres内核 Open WAL segment(包含 WAL 位置 ‘RecPtr’)(2 - 4)

上一篇: 文章目录 1. 打开 WAL Segment2. Standby mode 由一个 状态机(state machine)实现2.1 何处获取 WAL 文件?2.1.1 XLogSource2.1.2 从所选源(XLogSource )读取 XLOG2.1.2.1 walreceiver 运行状态 ?2.1.3 readFile(XLOG 文件句柄)1. 打开 WAL Segment 在经过前…...

Mysql基础

什么是关系型数据库&#xff1f; 顾名思义&#xff0c;关系型数据库&#xff08;RDB&#xff0c;Relational Database&#xff09;就是一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系&#xff08;一对一、一对多、多对多&#xff09;。 …...

Altium Designer学习笔记 24 PCB初始布局2

基于Altium Designer 23学习版&#xff0c;四层板智能小车PCB 更多AD学习笔记&#xff1a;Altium Designer学习笔记 1-5 工程创建_元件库创建Altium Designer学习笔记 6-10 异性元件库创建_原理图绘制Altium Designer学习笔记 11-15 原理图的封装 编译 检查 _PCB封装库的创建Al…...

【从0学英语】形容词性/名词性物主代词是什么?

在英语中&#xff0c;物主代词是非常重要的语法概念之一&#xff0c;特别是对于初学者来说。理解形容词性物主代词和名词性物主代词的不同&#xff0c;能够帮助我们在日常对话中准确地表达拥有关系。在这篇文章中&#xff0c;我们将深入探讨这两个概念&#xff0c;并通过详细的…...

hhdb数据库介绍(10-29)

管理 数据备份 从存储节点或灾备机房数据备份 选择灾备机房类型、从库&#xff08;双主备库&#xff09;存储节点类型进行备份&#xff0c;页面根据选择类型&#xff0c;对应给出提示信息。发起备份时&#xff0c;检测从存储节点状态是否符合备份条件。 主从数据一致性检测…...

springboot(20)(删除文章分类。获取、更新、删除文章详细)(Validation分组校验)

目录 一、删除文章分类功能。 &#xff08;1&#xff09;接口文档。 1、请求路径、请求参数。 2、请求参数。 3、响应数据。 &#xff08;2&#xff09;实现思路与代码书写。 1、controller层。 2、service接口业务层。 3、serviceImpl实现类。 4、mapper层。 5、后端接口测试。…...

实战指南:理解 ThreadLocal 原理并用于Java 多线程上下文管理

目录 一、ThreadLocal基本知识回顾分析 &#xff08;一&#xff09;ThreadLocal原理 &#xff08;二&#xff09;既然ThreadLocalMap的key是弱引用&#xff0c;GC之后key是否为null&#xff1f; &#xff08;三&#xff09;ThreadLocal中的内存泄漏问题及JDK处理方法 &…...

Spark 内存管理机制

Spark 内存管理 堆内内存和堆外内存 作为一个 JVM 进程&#xff0c;Executor 的内存管理建立在 JVM(最小为六十四分之一&#xff0c;最大为四分之一)的内存管理之上&#xff0c;此外spark还引入了堆外内存&#xff08;不在JVM中的内存&#xff09;&#xff0c;在spark中是指不…...

【Maven】继承和聚合

5. Maven的继承和聚合 5.1 什么是继承 Maven 的依赖传递机制可以一定程度上简化 POM 的配置&#xff0c;但这仅限于存在依赖关系的项目或模块中。当一个项目的多个模块都依赖于相同 jar 包的相同版本&#xff0c;且这些模块之间不存在依赖关系&#xff0c;这就导致同一个依赖…...

NViST运行笔记

文章标题&#xff1a; NViST: In the Wild New View Synthesis from a Single Image with Transformers 1. 环境配置 创建环境 conda create -n nvist python3.9 进入环境 conda activate nvist 安装torch torchvision torchaudio pip install torch2.1.2 torchvision0…...

性能测试工具Grafana、InfluxDB和Collectd的搭建

一、性能监控组成简介 1、监控能力分工:这个系统组合能够覆盖从数据采集、存储到可视化的整个监控流程。Collectd可以收集各种系统和应用的性能指标,InfluxDB提供高效的时序数据存储,而 Grafana 则将这些数据以直观的方式呈现出来。2,实时性能监控:对于需要实时了解系统状…...

JS中的类与对象

面向对象是使用最广泛的一种编程范式&#xff0c;最具代表性的面向对象语言就是Java和C&#xff0c;在它们的理念中&#xff0c;面向对象的三大特性&#xff1a;封装&#xff0c;继承&#xff0c;多态。类&#xff0c;对象&#xff0c;公有/私有方法/属性&#xff0c;各种继承就…...

域名解析系统 DNS

1.域名系统概述 用户与互联网上某台主机通信时&#xff0c;必须要知道对方的IP地址。然而用户很难记住长达32 位的二进制主机地址。即使是点分十进制地址也并不太容易记忆。但在应用层为了便于用户记忆各种网络应用&#xff0c;连接在互联网上的主机不仅有P地址&#xff0c;而…...

Flutter 1.1:下载Flutter环境

1、在AS中下载Flutter插件 在setting的Plugins中下载Flutter&#xff0c;如图所示&#xff0c;可以直接进行搜索查找 2、下载flutter的sdk源代码 flutter中文文档学习 通过Git下载SDK源代码 git clone -b stable https://github.com/flutter/flutter.git3、配置系统变量 3…...

HTML5系列(6)-- 拖放 API 实战指南

前端技术探索系列&#xff1a;HTML5 拖放 API 实战指南 &#x1f3af; 致读者&#xff1a;探索现代交互技术 &#x1f44b; 前端开发者们&#xff0c; 今天我们将深入探讨 HTML5 中一个强大而实用的特性 —— 拖放 API。这项技术能够让我们创建更加直观和交互性强的用户界面…...

windows下kafka初体验简易demo

这里提供了windows下的java1.8和kafka3.9.0版本汇总&#xff0c;可直接免费下载 【免费】java1.8kafka2.13版本汇总资源-CSDN文库 解压后可以得到一个文件夹 资料汇总内有一个kafka文件资料包.tgz&#xff0c;解压后可得到下述文件夹kafka_2.13-3.9.0&#xff0c;资料汇总内还…...

算法训练(leetcode)二刷第三十三天 | *322. 零钱兑换、*279. 完全平方数、*139. 单词拆分

刷题记录 *322. 零钱兑换*279. 完全平方数*139. 单词拆分 *322. 零钱兑换 leetcode题目地址 dp[j]存储amount为j时所需要的最少硬币数。当j为0时需要0个硬币&#xff0c;因此dp[0]赋值为0. 因为是取最少硬币数&#xff0c;因此初始化需要赋值一个最大值。 状态转移方程&…...

windows的pip镜像源配置

Windows 中 pip 镜像源配置 在 Windows 系统中&#xff0c;为了提高 pip 包的安装速度&#xff0c;我们可以配置 pip 的镜像源。以下是具体的配置步骤&#xff1a; 创建文件夹 在 C:\Users\Administrator\pip 路径下创建一个名为 pip.ini 的文件。 编辑 pip.ini 文件 使用文本…...

Django Rest Framework中嵌套关系的JSON序列化

在 Django Rest Framework (DRF) 中&#xff0c;处理嵌套关系的 JSON 序列化是一个常见需求。以下是如何实现嵌套关系序列化的详细说明&#xff0c;包括序列化器定义、模型关系以及常见用法。 1、问题背景 假设我们有以下两个模型&#xff1a; class Jobdtl(models.Model):jo…...

ONVIF协议网络摄像机客户端使用gsoap获取RTSP流地址GStreamer拉流播放

什么是ONVIF协议 ONVIF&#xff08;开放式网络视频接口论坛&#xff09;是一个全球性的开放式行业论坛&#xff0c;旨在促进开发和使用基于物理IP的安全产品接口的全球开放标准。 ONVIF规范的目标是建立一个网络视频框架协议&#xff0c;使不同厂商生产的网络视频产品完全互通。…...

40分钟学 Go 语言高并发:Go程序性能优化方法论

Go程序性能优化方法论 一、性能指标概述 指标类型关键指标重要程度优化目标CPU相关CPU使用率、线程数、上下文切换⭐⭐⭐⭐⭐降低CPU使用率&#xff0c;减少上下文切换内存相关内存使用量、GC频率、对象分配⭐⭐⭐⭐⭐减少内存分配&#xff0c;优化GC延迟指标响应时间、处理延…...

MySQL基础(语句)知识复习 (除索引和视图)

1.客户端和数据库操作 1.登录客户端界面&#xff1a;mysql -uroot -p 2.查看当前的数据库版本&#xff1a;select version(); 3.显示所有数据库&#xff1a;show databases;&#xff0c; 4.创建数据库&#xff1a;create [IF NOT EXISTS] database 库名 character set 字符…...

【sqlcipher】pc端sqflite使用过程中遇到的问题

在flutter中使用sqlcipher时 Mac上如果通过flutter带的文件管理api&#xff08;即File的delete()方法&#xff09;删除数据库文件&#xff0c;再创建同名的数据文件的话&#xff0c;必现readonly问题&#xff0c; 这里需要注意的一点是 DatabaseFactory 在Mac上直接使用全局的…...

Vue 实现无线滚动效果

目录 1.Element-plus官网中的Infinite Scroll组件说明 2.滚动条设置 3.滚动到底部的函数调用 1.Element-plus官网中的Infinite Scroll组件说明 官网链接如下所示&#xff1a; Infinite Scroll 无限滚动 | Element Plus 首先查看该代码&#xff0c;发现这个组件使用了一个…...

【CSS in Depth 2 精译_062】第 10 章 CSS 中的容器查询(@container)概述 + 10.1 容器查询的一个简单示例

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 【第十章 CSS 容器查询】 ✔️ 10.1 容器查询的一个简单示例 ✔️ 10.1.1 容器尺寸查询的用法 ✔️ 10.2 深入理解容器10.3 与容器相关的单位10.4 容器样式查询的用法10.5 本章小结 文章目录 第 10…...

conda手动初始化

问题:环境中存在conda但是conda无法使用 方法: 进入到anaconda目录下, 进入bin目录, 然后执行 source activate要想启动时自动进入conda环境, 需要在 ~/.bashrc中添加如下命令 # >>> conda initialize >>> # !! Contents within this block are managed by …...

hhdb数据库介绍(10-28)

管理 管理菜单主要囊括对业务数据进行管理的功能&#xff0c;例如对数据的备份恢复或执行业务表的DDL语句等操作。 数据对象 数据对象功能可以帮助用户通过列表实时查看当前已存在的数据对象&#xff0c;了解业务数据的整体情况。提供了对数据对象的筛选、统计、关联、详情等…...

Spring Boot自定义启动banner

在启动 Springboot 应用时&#xff0c;默认情况下会在控制台打印出 Springboot 相关的banner信息。 自定义banner 如果你想自定义一个独特的启动banner&#xff0c;该怎么做呢&#xff1f;Springboot 允许我们通过自定义启动banner来替换默认的banner。只需要在 resources 目…...

c语言——数组名该如何理解呢?

一般情况下&#xff0c;数组名表示首元素地址&#xff0c;以下2种除外&#xff1a; ①、sizeof(数组名) 表示整个数组 ※只有数组名的情况 sizeof&#xff08;数组名i&#xff09; 就不能表示整个数组 ②、&数组名 表示整个数组&#xff0c;取的是整个数…...

前端 如何用 div 标签实现 步骤审批

在前端实现一个步骤审批流程&#xff0c;通常是通过 div 标签和 CSS 来构建一个可视化的流程图&#xff0c;结合 JavaScript 控制审批的状态变化。你可以使用 div 标签创建每一个步骤节点&#xff0c;通过不同的样式&#xff08;如颜色、边框等&#xff09;表示审批的不同状态&…...

QT工程,它该怎么学?

在现代软件开发中&#xff0c;QT因其强大的跨平台能力和友好的用户界面设计工具&#xff0c;成为开发者学习和应用的热门选择。特别是在Linux系统下&#xff0c;如何安装、配置QT开发环境&#xff0c;以及创建和管理QT工程是入门QT开发的关键环节。本文将从安装QT开发环境开始&…...

第426场周赛:仅含置位位的最小整数、识别数组中的最大异常值、连接两棵树后最大目标节点数目 Ⅰ、连接两棵树后最大目标节点数目 Ⅱ

Q1、仅含置位位的最小整数 1、题目描述 给你一个正整数 n。 返回 大于等于 n 且二进制表示仅包含 置位 位的 最小 整数 x 。 置位 位指的是二进制表示中值为 1 的位。 2、解题思路 我们需要找到一个整数 x&#xff0c;使得&#xff1a; x ≥ nx 的二进制表示中仅包含置位…...

23种设计模式之外观模式

目录 1. 简介2. 代码2.1 SelectFoodService (选择食品)2.2 PayService (支付服务)2.3 TakeService (制作服务)2.4 OrderService (下单服务)2.5 Food (食品)2.6 TackingSystem &#xff08;外观类&#xff09;2.7 Test &#xff08;测试类&#xff09; 3. 优缺点3. 总结 1. 简介…...

【智商检测——DP】

题目 代码 #include <bits/stdc.h> using namespace std; const int N 1e510, M 110; int f[N][M]; int main() {int n, k;cin >> n >> k;for(int i 1; i < n; i){int x;cin >> x;f[i][0] __gcd(f[i-1][0], x);for(int j 1; j < min(i, k)…...

LeetCode-430. 扁平化多级双向链表-题解

题目链接 430. 扁平化多级双向链表 - 力扣&#xff08;LeetCode&#xff09; 题目介绍 你将得到一个双链表&#xff0c;节点包含一个“下一个”指针、一个“前一个”指针和一个额外的“子指针”。这个子指针可能指向一个单独的双向链表&#xff0c;并且这些链表也包含类似的特殊…...

【CSS】一篇掌握CSS

不是因为有了希望才去坚持,而是坚持了才有了希望 目录 一.导入方式 1.行内样式 2.内部样式 3.外部样式(常用) 二.选择器 1.基本选择器(常用) 1.1标签选择器 1.2类选择器 1.3id选择器 2.层次选择器 2.1后代选择器 2.2子选择器 2.3相邻兄弟选择器 2.4通用兄弟选择器…...

华为仓颉编程环境搭建

1、仓颉介绍 摘自华为官方&#xff1a;仓颉编程语言作为一款面向全场景应用开发的现代编程语言&#xff0c;通过现代语言特性的集成、全方位的编译优化和运行时实现、以及开箱即用的 IDE 工具链支持&#xff0c;为开发者打造友好开发体验和卓越程序性能。 其具体特性表现为&am…...

手机实时提取SIM卡打电话的信令声音-蓝牙电话如何适配eSIM卡的手机

手机实时提取SIM卡打电话的信令声音 --蓝牙电话如何适配eSIM卡的手机 一、前言 蓝牙电话的海外战略中&#xff0c;由于海外智能手机市场中政策的差异性&#xff0c;对内置eSIM卡的手机进行支持是非常合理的需求。Android系列手机中&#xff0c;无论是更换通信运营商&#xf…...

三种方式(oss、本地、minio)图片的上传下载

一、OSS 1、前期准备 1.1 注册阿里云账号&#xff0c;开启对象存储oss功能&#xff0c;创建一个bucket&#xff08;百度教程多的是&#xff0c;跟着创建一个就行&#xff0c;创建时注意存储类型是标准存储&#xff0c;读写权限是公共读&#xff09; 有的在创建桶时读写属性是…...