常见持久层框架赏析,到底是什么让你选择 MyBatis?

news2024/11/25 21:21:13

在绝大多数在线应用场景中,数据是存储在关系型数据库中的,当然,有特殊要求的场景中,我们也会将其他持久化存储(如 ElasticSearch、HBase、MongoDB 等)作为辅助存储。但不可否认的是,关系型数据库凭借几十年的发展、生态积累、众多成功的案例,依然是互联网企业的核心存储。

作为一个 Java 开发者,几乎天天与关系型数据库打交道,在生产环境中常用的关系型数据库产品有 SQL Server、MySQL、Oracle 等。在使用这些数据库产品的时候,基本上是如下思路:

  • 在写 Java 代码的过程中,使用的是面向对象的思维去实现业务逻辑;

  • 在设计数据库表的时候,考虑的是第一范式、第二范式和第三范式;

  • 在操作数据库记录的时候,使用 SQL 语句以及集合思维去考虑表的连接、条件语句、子查询等的编写。

这个时候,就需要一座桥梁将 Java 类(或是其他数据结构)与关系型数据库中的表,以及 Java 对象与表中的数据映射起来,实现 Java 程序与数据库之间的交互。

JDBC(Java DataBase Connectivity)是 Java 程序与关系型数据库交互的统一 API。实际上,JDBC 由两部分 API 构成:第一部分是面向 Java 开发者的 Java API,它是一个统一的、标准的 Java API,独立于各个数据库产品的接口规范;第二部分是面向数据库驱动程序开发者的 API,它是由各个数据库厂家提供的数据库驱动,是第一部分接口规范的底层实现,用于连接具体的数据库产品。

在实际开发 Java 程序时,我们可以通过 JDBC 连接到数据库,并完成各种各样的数据库操作,例如 CRUD 数据、执行 DDL 语句。这里以 JDBC 编程中执行一条 Select 查询语句作为例子,说明 JDBC 操作的核心步骤,具体如下:

  1. 注册数据库驱动类,指定数据库地址,其中包括 DB 的用户名、密码及其他连接信息;

  2. 调用 DriverManager.getConnection() 方法创建 Connection 连接到数据库;

  3. 调用 Connection 的 createStatement() 或 prepareStatement() 方法,创建 Statement 对象,此时会指定 SQL(或是 SQL 语句模板 + SQL 参数);

  4. 通过 Statement 对象执行 SQL 语句,得到 ResultSet 对象,也就是查询结果集;

  5. 遍历 ResultSet,从结果集中读取数据,并将每一行数据库记录转换成一个 JavaBean 对象;

  6. 关闭 ResultSet 结果集、Statement 对象及数据库 Connection,从而释放这些对象占用的底层资源。

无论是执行查询操作,还是执行其他 DML 操作,1、2、3、4、6 这些步骤都会重复出现。为了简化重复逻辑,提高代码的可维护性,可以将上述重复逻辑封装到一个类似 DBUtils 的工具类中,在使用时只需要调用 DBUtils 工具类中的方法即可。当然,我们也可以使用“反射+配置”的方式,将步骤 5 中关系模型到对象模型的转换进行封装,但是这种封装要做到通用化且兼顾灵活性,就需要一定的编程功底。

为了处理上述代码重复的问题以及后续的维护问题,我们在实践中会进行一系列评估,选择一款适合项目需求、符合人员能力的 ORM(Object Relational Mapping,对象-关系映射)框架来封装 1~6 步的重复性代码,实现对象模型、关系模型之间的转换。这正是ORM 框架的核心功能:根据配置(配置文件或是注解)实现对象模型、关系模型两者之间无感知的映射(如下图)。

对象模型与关系模型的映射

在生产环境中,数据库一般都是比较稀缺的,数据库连接也是整个服务中比较珍贵的资源之一。建立数据库连接涉及鉴权、握手等一系列网络操作,是一个比较耗时的操作,所以我们不能像上述 JDBC 基本操作流程那样直接释放掉数据库连接,否则持久层很容易成为整个系统的性能瓶颈。

Java 程序员一般会使用数据库连接池的方式进行优化,此时就需要引入第三方的连接池实现,当然,也可以自研一个连接池,但是要处理连接活跃数、控制连接的状态等一系列操作还是有一定难度的。另外,有一些查询返回的数据是需要本地缓存的,这样可以提高整个程序的查询性能,这就需要缓存的支持。

如果没有 ORM 框架的存在,这就需要我们 Java 开发者熟悉相关连接池、缓存等组件的 API 并手动编写一些“黏合”代码来完成集成,而且这些代码重复度很高,这显然不是我们希望看到的结果。

很多 ORM 框架都支持集成第三方缓存、第三方数据源等常用组件,并对外提供统一的配置接入方式,这样我们只需要使用简单的配置即可完成第三方组件的集成。当我们需要更换某个第三方组件的时候,只需要引入相关依赖并更新配置即可,这就大大提高了开发效率以及整个系统的可维护性

下面我们就简单介绍一下在实践中常用的几种 ORM 框架。

Hibernate

Hibernate 是 Java 生态中著名的 ORM 框架之一。Hibernate 现在也在扩展自己的生态,开始支持多种异构数据的持久化,不仅仅提供 ORM 框架,还提供了 Hibernate Search 来支持全文搜索,提供 validation 来进行数据校验,提供 Hibernate OGM 来支持 NoSQL 解决方案。

这里我们要重点讲解的是 Hibernate ORM 的相关内容,截至 2020 年底,Hibernate ORM 的最新版本是 5.4 版本,6.0 版本还正在开发中。作为一个老牌的 ORM 框架,Hibernate 经受住了 Java EE 企业级应用的考验,一度成为 Java ORM 领域的首选框架。

在使用 Hibernate 的时候,Java 开发可以使用映射文件或是注解定义 Java 语言中的类与数据库中的表之间的各种映射关系,这里使用到的映射文件后缀为“.hbm.xml”。hbm.xml 映射文件将一张数据库表与一个 Java 类进行关联之后,该数据库表中的每一行记录都可以被转换成对应的一个 Java 对象。正是由于 Hibernate 映射的存在,Java 开发只需要使用面向对象思维就可以完成数据库表的设计。

在 Java 这种纯面向对象的语言中,两个 Java 对象之间可能存在一对一、一对多或多对多等复杂关联关系。Hibernate 中的映射文件也必须要能够表达这种复杂关联关系才能够满足我们的需求,同时,还要能够将这种关联关系与数据库中的关联表、外键等一系列关系模型中的概念进行映射,这也就是 ORM 框架中常提到的“关联映射”。

下面我们就来结合示例介绍“一对多”关联关系。例如,一个顾客(Customer)可以创建多个订单(Order),而一个订单(Order)只属于一个顾客(Customer),两者之间存在一对多的关系。在 Java 程序中,可以在 Customer 类中添加一个 List 类型的字段来维护这种一对多的关系;在数据库中,可以在订单表(t_order)中添加一个 customer_id 列作为外键,指向顾客表(t_customer)的主键 id,从而维护这种一对多的关系,如下图所示:

关系模型中的一对多和对象模型中的一对多

在 Hibernate 中,可以通过如下 Customer.hbm.xml 配置文件将这两种关系进行映射:

<hibernate-mapping>
    <!-- 这里指定了Customer类与t_customer表之间的映射 -->
    <class name="com.mybatis.test.Customer" table="t_customer">
        <!-- Customer类中的id属性与t_customer表中主键id之间的映射 -->
        <id name="id" column="id"/>
        <!-- Customer类中的name属性与t_customer表中name字段之间的映射 -->
        <property name="name" column="name"/>
        <!-- Customer指定了Order与Customer 一对多的映射关系 -->
        <set name="orders" cascade="save,update,delete">
            <key column="customer_id"/>
            <one-to-many class="com.mybatis.test.Order"/>
        </set>
    </class>
</hibernate-mapping>

如果是双向关联,则在 Java 代码中,可以直接在 Order 类中添加 Customer 类型的字段指向关联的 Customer 对象,并在相应的 Order.hbm.xml 配置文件中进行如下配置:

<hibernate-mapping>
    <!-- 这里指定了Order类与t_order表之间的映射 -->
    <class name="com.mybatis.test.Order" table="t_order">
        <!-- Order类中的id属性与t_order表中主键id之间的映射 -->
        <id name="id" column="id"/>
        <!-- Order类中的address属性与t_order表中address列之间的映射 -->
        <property name="address" column="address"/>
        <!-- Order类中的tele属性与t_order表中tele列之间的映射 -->
        <property name="tele" column="tele"/>
        <!-- Order类中customer属性与t_order表中customer_id之间的映射,
             同时也指定Order与Customer之间的多对一的关系 -->
        <many-to-one name="customer" column="customer_id"></many-to-one>
    </class>
</hibernate-mapping>

一对一、多对多等关联映射在 Hibernate 映射文件中,都定义了相应的 XML 标签,原理与“一对多”基本一致,只是使用方式和场景略有不同,这里就不再展开介绍,你若感兴趣的话可以参考 Hibernate 的官方文档进行学习。

除了能够完成面向对象模型与数据库中关系模型的映射,Hibernate 还可以帮助我们屏蔽不同数据库产品中 SQL 语句的差异。

我们知道,虽然目前有 SQL 标准,但是不同的关系型数据库产品对 SQL 标准的支持有细微不同,这就会出现一些非常尴尬的情况,例如,一条 SQL 语句在 MySQL 上可以正常执行,而在 Oracle 数据库上执行会报错。

Hibernate封装了数据库层面的全部操作,Java 程序员不再需要直接编写 SQL 语句,只需要使用 Hibernate 提供的 API 即可完成数据库操作。

例如,Hibernate 为用户提供的 Criteria 是一套灵活的、可扩展的数据操纵 API,最重要的是 Criteria 是一套面向对象的 API,使用它操作数据库的时候,Java 开发者只需要关注 Criteria 这套 API 以及返回的 Java 对象,不需要考虑数据库底层如何实现、SQL 语句如何编写,等等。

下面是 Criteria API 的一个简单示例:

// 创建Criteria对象,用来查询Customer对象
Criteria criteria = session.createCriteria(Customer.class, "u");
//查询出id大于0,且名字中以yang开头的顾客数据
List<Customer> list = criteria.add(Restrictions.like("name","yang%"))
                            .add(Restrictions.gt("id", 0))
                            .list();

除了 Criteria API 之外,Hibernate 还提供了一套面向对象的查询语言—— HQL(Hibernate Query Language)。从语句的结构上来看,HQL 语句与 SQL 语句十分类似,但这二者也是有区别的:HQL 是面向对象的查询语言,而 SQL 是面向关系型的查询语言

在实现复杂数据库操作的时候,我们可以使用 HQL 这种面向对象的查询语句来实现,Hibernate 的 HQL 引擎会根据底层使用的数据库产品,将 HQL 语句转换成合法的 SQL 语句。

Hibernate 通过其简洁的 API 以及统一的 HQL 语句,帮助上层程序屏蔽掉底层数据库的差异,增强了程序的可移植性。

另外,Hibernate 还具有如下的一些其他优点:

  • Hibernate API 本身没有侵入性,也就是说,业务逻辑感知不到 Hibernate 的存在,也不需要继承任何 Hibernate 包中的接口;

  • Hibernate 默认提供一级缓存、二级缓存(一级缓存默认开启,二级缓存需要配置开启),这两级缓存可以降低数据库的查询压力,提高服务的性能;

  • Hibernate 提供了延迟加载的功能,可以避免无效查询;

  • Hibernate 还提供了由对象模型自动生成数据库表的逆向操作。

但需要注意的是,Hibernate 并不是一颗“银弹”,我们无法在面向对象模型中找到数据库中所有概念的映射,例如,索引、函数、存储过程等。在享受 Hibernate 带来便捷的同时,我们还需要忍受它的一些缺点。例如,索引对提升数据库查询性能有很大帮助,我们建立索引并适当优化 SQL 语句,就会让数据库使用合适的索引提高整个查询的速度。但是,我们很难修改 Hibernate 生成的 SQL 语句。为什么这么说呢?因为在一些场景中,数据库设计非常复杂,表与表之间的关系错综复杂,Hibernate 引擎生成的 SQL 语句会非常难以理解,要让生成的 SQL 语句使用正确的索引更是难上加难,这就很容易生成慢查询 SQL。

另外,在一些大数据量、高并发、低延迟的场景中,Hibernate 在性能方面带来的损失就会逐渐显现出来。

当然,从其他角度来看 Hibernate,还会有一些其他的问题,这里就不再展开介绍,你若感兴趣的话可以自行去查阅一些资料进行深入了解。

Spring Data JPA

在开始介绍 Spring Data JPA 之前,我们先要来介绍一下 JPA(Java Persistence API)规范。

JPA 是在 JDK 5.0 后提出的 Java 持久化规范(JSR 338)。JPA 规范本身是为了整合市面上已有的 ORM 框架,结束 Hibernate、EclipseLink、JDO 等 ORM 框架各自为战的割裂局面,简化 Java 持久层开发。

JPA 规范从现有的 ORM 框架中借鉴了很多优点,例如,Gavin King 作为 Hibernate 创始人,同时也参与了 JPA 规范的编写,所以在 JPA 规范中可以看到很多与 Hibernate 类似的概念和设计。

既然 JPA 是一个持久化规范,没有提供具体持久化实现,那谁来提供实现呢?答案是市面上的 ORM 框架,例如,Hibernate、EclipseLink 等都提供了符合 JPA 规范的具体实现,如下图所示:

JPA 生态图

JPA 有三个核心部分:ORM 映射元数据、操作实体对象 API 和面向对象的查询语言(JPQL)。这与 Hibernate 的核心功能基本类似,就不再重复讲述。

Java 开发者应该都知道“Spring 全家桶”的强大,Spring 目前已经成为事实上的标准了,很少有企业会完全离开 Spring 来开发 Java 程序。现在的 Spring 已经不仅仅是最早的 IoC 容器了,而是整个 Spring 生态,例如,Spring Cloud、Spring Boot、Spring Security 等,其中就包含了 Spring Data。

Spring Data 是 Spring 在持久化方面做的一系列扩展和整合,下图就展示了 Spring Data 中的子项目:

Spring Data 生态图

Spring Data 中的每个子项目都对应一个持久化存储,通过不断的整合接入各种持久化存储的能力,Spring 的生态又向前迈进了一大步,其中最常被大家用到的应该就是 Spring Data JPA。

Spring Data JPA 是符合 JPA 规范的一个 Repository 层的实现,其所在的位置如下图所示:

Spring Data JPA 生态图

虽然市面上的绝大多数 ORM 框架都实现了 JPA 规范,但是它们在 JPA 基础上也有各自的发展和修改,这样导致我们在使用 JPA 的时候,依旧无法无缝切换底层的 ORM 框架实现。而使用 Spring Data JPA 时,由于Spring Data JPA 帮助我们抹平了各个 ORM 框架的差异,从而可以让我们的上层业务无缝地切换 ORM 实现框架

MyBatis

Apache 基金会中的 iBatis 项目是 MyBatis 的前身。iBatis 项目由于各种原因,在 Apache 基金会并没有得到很好的发展,最终于 2010 年脱离 Apache,并更名为 MyBatis。三年后,也就是 2013 年,MyBatis 将源代码迁移到了 GitHub。

MyBatis 中一个重要的功能就是可以帮助 Java 开发封装重复性的 JDBC 代码,这与前文分析的 Spring Data JPA 、Hibernate 等 ORM 框架一样。MyBatis 封装重复性代码的方式是通过 Mapper 映射配置文件以及相关注解,将 ResultSet 结果映射为 Java 对象,在具体的映射规则中可以嵌套其他映射规则和必要的子查询,这样就可以轻松实现复杂映射的逻辑,当然,也能够实现一对一、一对多、多对多关系映射以及相应的双向关系映射。

很多人会将 Hibernate 和 MyBatis 做比较,认为 Hibernate 是全自动 ORM 框架,而 MyBatis 只是半自动的 ORM 框架或是一个 SQL 模板引擎。其实,这些比较都无法完全说明一个框架比另一个框架先进,关键还是看应用场景。

MyBatis 相较于 Hibernate 和各类 JPA 实现框架更加灵活、更加轻量级、更加可控

  • 我们可以在 MyBatis 的 Mapper 映射文件中,直接编写原生的 SQL 语句,应用底层数据库产品的方言,这就给了我们直接优化 SQL 语句的机会;

  • 我们还可以按照数据库的使用规则,让原生 SQL 语句选择我们期望的索引,从而保证服务的性能,这就特别适合大数据量、高并发等需要将 SQL 优化到极致的场景

  • 在编写原生 SQL 语句时,我们也能够更加方便地控制结果集中的列,而不是查询所有列并映射对象后返回,这在列比较多的时候也能起到一定的优化效果。(当然,Hibernate 也能实现这种效果,需要在实体类添加对应的构造方法。)

在实际业务中,对同一数据集的查询条件可能是动态变化的,如果你有使用 JDBC 或其他类似框架的经历应该能体会到,拼接 SQL 语句字符串是一件非常麻烦的事情,尤其是条件复杂的场景中,拼接过程要特别小心,要确保在合适的位置添加“where”“and”“in”等 SQL 语句的关键字以及空格、逗号、等号等分隔符,而且这个拼接过程非常枯燥、没有技术含量,可能经过反复调试才能得到一个可执行的 SQL 语句。

MyBatis 提供了强大的动态 SQL 功能来帮助我们开发者摆脱这种重复劳动,我们只需要在映射配置文件中编写好动态 SQL 语句,MyBatis 就可以根据执行时传入的实际参数值拼凑出完整的、可执行的 SQL 语句。

总结

我们重点介绍了 3 种常见的 ORM 持久化框架,那在实际工作中我们又应该如何选择合适的持久层框架呢?

  • 性能角度来看,Hibernate、Spring Data JPA 在对 SQL 语句的掌控、SQL 手工调优、多表连接查询等方面,不及 MyBatis 直接使用原生 SQL 语句方便、高效;

  • 可移植性角度来看,Hibernate 帮助我们屏蔽了底层数据库方言,Spring Data JPA 帮我们屏蔽了 ORM 的差异,而 MyBatis 因为直接编写原生 SQL,会与具体的数据库完全绑定(但实践中很少有项目会来回切换底层使用的数据库产品或 ORM 框架,所以这点并不是特别重要);

  • 开发效率角度来看,Hibernate、Spring Data JPA 处理中小型项目的效率会略高于 MyBatis(这主要还是看需求和开发者技术栈)。

除了这三方面之外,还有很多方面需要在技术选型中考虑进去,例如,预估的 QPS、P99 等性能指标,等等。在技术选型时,我们也要统筹考虑更多方面,才能选出最合适自己的方案。

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

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

相关文章

Ubuntu20.04操作系统安装及重中之重:系统分区

最近因为学习原因&#xff0c;需要将电脑设置为双系统&#xff0c;在windows10的系统下去安装Ubuntu操作系统。本来看网上相关的安装教程蛮多的&#xff0c;以为比较简单&#xff0c;结果一路过五关斩六将&#xff0c;坑的七零八落的&#xff0c;折腾了好久&#xff0c;才算安装…

【Java】LinkedList 集合

LinkedList集合特点 LinkedList 底层基于双向链表实现增删 效率非常高&#xff0c;查询效率非常低。 LinkedList源码解读分析 LinkedList 是双向链表实现的 ListLinkedList 是非线程安全的&#xff08;线程是不安全的&#xff09;LinkedList 元素允许为null,允许重复元素Linked…

基于 ARM+FPGA+AD的高精度数据采集系统设计

随着图像处理 、 工业控制 、 无线通信等领域的飞速发 展 &#xff0c; 对数据采集系统的速度 、 精度等性能要求也越来越高 。 这些要求都对数据采集系统的设计和实现提出了新的挑 战 。 目前数据采集系统的设计方案通常分为以下几类 &#xff1a; &#xff11; &#xff0…

【持续交付】个人网站

今天给大家演示下如何基于Vuepress尝试持续交付博客网站。 也尝试过其他的方案&#xff0c;比如使用Typora导出html文件&#xff0c;并scp该文件到服务器上。 效果图 该持续交付主流程如下图 提交代码后会触发webHook生成version.txt,部署脚本每分钟轮询一次检测是否存在vers…

私有云:【14】桌面映射外网

私有云&#xff1a;【14】桌面映射外网 1、选择服务器设置2、选中以下项&#xff0c;填写自己的公网IP3、最后这个也修改掉 1、选择服务器设置 2、选中以下项&#xff0c;填写自己的公网IP 3、最后这个也修改掉 桌面映射外网设置完成&#xff0c;前提要有公网IP噶&#xff0c;…

Docker 笔记(上篇)

Docker 概述 Docker 概念 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之…

【算法练习Day32】 斐波那契数爬楼梯使用最小花费爬楼梯

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 斐波那契数爬楼梯使用最小花…

所有电商API接口,淘宝API接口分类,1688API、拼多多API、京东API

前往接入API 淘宝API item_get 获取商品详情 根据商品ID查询商品标题价格描述等详情数据 淘宝API item_search 按关键字搜索商品 搜索关键字&#xff0c;显示商品总数&#xff0c;标题&#xff0c;图片&#xff0c;优惠价等数据 淘宝API item_fee 获取商品快递费用 输入商品…

基于RK3568高性价比全国产EMS储能解决方案(一)概述

储能产业链框架 储能产业链可分为上游“原材料及生产设备”、中游“储能系统”、下游“储能场景应用及后市场服务”。 图1 储能产业链框架图 产业链中游的“储能电池系统”主要包括“能量管理系统(EMS)”、“电池管理系统(BMS)”、“储能逆变器(PCS)”、“电池组”四个部分。…

Java创建一个长度为10的数组,利用Arrays.sort(), 为数组元素排序

程序要求&#xff1a;1&#xff09;创建一个整型数组&#xff0c;数组的长度为10. 2&#xff09;给数组元素赋值&#xff0c;要求乱序。 3&#xff09;利用fori循环将数组元素依次输出。 4&#xff09;利用Arrays.sort(), 为数组元素排序 5&#xff09;采用增加for循环将排…

shell语法大全(超级详细!!!!),非常适合入门

本文旨在对y总的Linux基础课shell语法做学习记录&#xff0c;指令较多&#xff0c;方便日后查找。 参考视频&#xff1a;Linux基础课 参考教程&#xff1a;Linux教程 1 概论 Linux中常见的shell脚本有很多种&#xff0c;常见的有&#xff1a; Bourne Shell(/usr/bin/sh或/bi…

Evade Deep Image Retrieval by Stashing Private Images in the Hash Space

摘要&#xff1a; 挑战&#xff1a; 当网络上的图像被大规模检索并被用作个人信息的丰富矿藏时&#xff0c;隐私也面临着风险&#xff1b; 攻击者可以通过从目标类别中查询类似图像以查找任何可用模型来提取私有图像。 提出&#xff1a; 提出了一种基于对抗性示例的新机制…

Cesium绕点旋转

目录 项目地址实现效果实现方法 项目地址 https://github.com/zhengjie9510/webgis-demo 实现效果 实现方法 let angle 0.0 viewer.camera.lookAt(position, new Cesium.HeadingPitchRange(Cesium.Math.toRadians(angle), Cesium.Math.toRadians(-30), 2000)) viewer.clock…

Ubuntu自建git服务器

Ubuntu 安装 gitlab-ce sudo apt-get update sudo apt-get install gitlab-ce 安装成功 sudo apt-get install gitlab-ce 正在读取软件包列表... 完成 正在分析软件包的依赖关系树 正在读取状态信息... 完成 下列【新】软件包将被安装&#xff1a;gitlab-ce 升…

基于鸟群算法的无人机航迹规划-附代码

基于鸟群算法的无人机航迹规划 文章目录 基于鸟群算法的无人机航迹规划1.鸟群搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用鸟群算法来优化无人机航迹规划。 1.鸟群搜索算法 …

koa搭建服务器(二)

在上一篇文章已经成功的运行了一个http服务器&#xff0c;接下来就是使用Sequelize ORM&#xff08;官方文档&#xff1a;Sequelize 简介 | Sequelize中文文档 | Sequelize中文网&#xff09;来操作数据库。 1、安装依赖 首先也是需要安装相关的依赖 npm i sequelize npm i …

【Mysql】数据库三大范式

数据库三范式 &#xff1a;数据库三范式是指关系型数据库设计中的三种规范化设计原则&#xff0c;旨在减少数据冗余、提高数据一致性和可维护性。 第一范式&#xff1a;规定表中的每一列都应该是不可分割的最小单元。 为什么要这样实现呢&#xff1f; &#xff1a;举个栗子…

【Unity PlasticSCM】记录:从介绍 下载 到拉取项目

实习的时候项目是svn管理的&#xff0c;这次mini的项目管理最后选择了美术策划友好的plasticSCM&#xff0c;但之前没有接触过&#xff0c;所以决定花费一点时间去了解&#xff0c;然后记录一下中间遇到的一些问题。 了解及下载Plastic b站很详细介绍PlasticSCM&#xff1a;Un…

ChatGPT扩展系列之ChatExcel

文章目录 ChatGPT扩展系列之ChatExcel对某一列的文字进行处理对数据进行排序对数据进行计算微软官方又推出Excel AI插件ChatGPT扩展系列之ChatExcel 自从ChatGPT很空出世之后,很多基于ChatGPT的应用便如雨后春笋般应用而生,这些应用的底层本质就是利用了ChatGPT对自然语言的…

计网强化

文章目录 1.TCP报文段、IP分组、MAC帧(1)TCP报文段 首部字段①发送窗口、接收窗口、拥塞窗口、滑动窗口(2)IP数据报 首部格式①片偏移量(3)MAC帧2.转发表、路由表、ARP表3.网络三层设备(1)集线器、交换机、路由器(2)冲突域与广播域(3)广播(4)时延