不好意思,Mybatis Plus 该换了

2023-09-21 16:28:34

使用fluent mybatis可以不用写具体的xml文件,通过java api可以构造出比较复杂的业务sql语句,做到代码逻辑和sql逻辑的合一。

不再需要在Dao中组装查询或更新操作,在xml或mapper中再组装参数。那对比原生Mybatis, Mybatis Plus或者其他框架,FluentMybatis提供了哪些便利呢?

Part1 仓库地址

详细的API及用法,可参考官方仓库

https://gitee.com/fluent-mybatis/fluent-mybatis

Part2 需求场景设置

我们通过一个比较典型的业务需求来具体实现和对比下,假如有学生成绩表结构如下:

create table `student_score`
(
    id           bigint auto_increment comment  '主键ID' primary key,
    student_id   bigint            not null comment  '学号',
    gender_man   tinyint default 0 not null comment  '性别, 0:女; 1:男',
    school_term  int               null comment  '学期',
    subject      varchar(30)       null comment  '学科',
    score        int               null comment  '成绩',
    gmt_create   datetime          not null comment  '记录创建时间',
    gmt_modified datetime          not null comment  '记录最后修改时间',
    is_deleted   tinyint default 0 not null comment  '逻辑删除标识'
) engine = InnoDB default charset=utf8;

现在有需求:

统计2000年三门学科('英语', '数学', '语文')及格分数按学期,学科统计最低分,最高分和平均分, 且样本数需要大于1条,统计结果按学期和学科排序

我们可以写SQL语句如下

select school_term,
       subject,
       count(score) as count,
       min(score)   as min_score,
       max(score)   as max_score,
       avg(score)   as max_score
from student_score
where school_term >= 2000
  and subject  in ( '英语',  '数学',  '语文')
  and score >= 60
  and is_deleted = 0
group by school_term, subject
having count(score) > 1
order by school_term, subject;

那上面的需求,分别用fluent mybatis, 原生mybatis 和 Mybatis plus来实现一番。

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

Part3 三者实现对比

1使用fluent mybatis 来实现上面的功能

2367a50867456c98d4b5f49441f829dd.jpeg

我们可以看到fluent api的能力,以及IDE对代码的渲染效果。

2、换成mybatis原生实现效果

定义Mapper接口

> summaryScore(SummaryQuery paras);}定义接口需要用到的参数实体 SummaryQuery@Data@Accessors(chain = true)public class SummaryQuery {    private Integer schoolTerm;    private List subjects;    private Integer score;    private Integer minCount;}定义实现业务逻辑的mapper xml文件    select school_term,    subject,    count(score) as count,    min(score) as min_score,    max(score) as max_score,    avg(score) as max_score    from student_score    where school_term >= #{schoolTerm}    and subject in            #{item}        and score >= #{score}    and is_deleted = 0    group by school_term, subject    having count(score) > #{minCount}    order by school_term, subject实现业务接口(这里是测试类, 实际应用中应该对应Dao类)@RunWith(SpringRunner.class)@SpringBootTest(classes = QuickStartApplication.class)public class MybatisDemo {    @Autowired    private MyStudentScoreMapper mapper;    @Test    public void mybatis_demo() {        // 构造查询参数        SummaryQuery paras = new SummaryQuery()            .setSchoolTerm(2000)            .setSubjects(Arrays.asList("英语", "数学", "语文"))            .setScore(60)            .setMinCount(1);        List> summary = mapper.summaryScore(paras);        System.out.println(summary);    }}总之,直接使用mybatis,实现步骤还是相当的繁琐,效率太低。那换成mybatis plus的效果怎样呢?" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2"> public interface MyStudentScoreMapper {
&nbsp;&nbsp;&nbsp;&nbsp;List<Map<String,&nbsp;Object>>&nbsp;summaryScore(SummaryQuery&nbsp;paras);
}

定义接口需要用到的参数实体 SummaryQuery

定义实现业务逻辑的mapper xml文件

>&nbsp;summaryScore(SummaryQuery&nbsp;paras);}定义接口需要用到的参数实体 SummaryQuery@Data@Accessors(chain&nbsp;=&nbsp;true)public&nbsp;class&nbsp;SummaryQuery&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Integer&nbsp;schoolTerm;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;List&nbsp;subjects;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Integer&nbsp;score;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Integer&nbsp;minCount;}定义实现业务逻辑的mapper xml文件&nbsp;&nbsp;&nbsp;&nbsp;select&nbsp;school_term,&nbsp;&nbsp;&nbsp;&nbsp;subject,&nbsp;&nbsp;&nbsp;&nbsp;count(score)&nbsp;as&nbsp;count,&nbsp;&nbsp;&nbsp;&nbsp;min(score)&nbsp;as&nbsp;min_score,&nbsp;&nbsp;&nbsp;&nbsp;max(score)&nbsp;as&nbsp;max_score,&nbsp;&nbsp;&nbsp;&nbsp;avg(score)&nbsp;as&nbsp;max_score&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;student_score&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;school_term&nbsp;>=&nbsp;#{schoolTerm}&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;subject&nbsp;in&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#{item}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;score&nbsp;>=&nbsp;#{score}&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;is_deleted&nbsp;=&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;group&nbsp;by&nbsp;school_term,&nbsp;subject&nbsp;&nbsp;&nbsp;&nbsp;having&nbsp;count(score)&nbsp;>&nbsp;#{minCount}&nbsp;&nbsp;&nbsp;&nbsp;order&nbsp;by&nbsp;school_term,&nbsp;subject实现业务接口(这里是测试类, 实际应用中应该对应Dao类)@RunWith(SpringRunner.class)@SpringBootTest(classes&nbsp;=&nbsp;QuickStartApplication.class)public&nbsp;class&nbsp;MybatisDemo&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;@Autowired&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;MyStudentScoreMapper&nbsp;mapper;&nbsp;&nbsp;&nbsp;&nbsp;@Test&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;mybatis_demo()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;构造查询参数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SummaryQuery&nbsp;paras&nbsp;=&nbsp;new&nbsp;SummaryQuery()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setSchoolTerm(2000)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setSubjects(Arrays.asList("英语",&nbsp;"数学",&nbsp;"语文"))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setScore(60)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setMinCount(1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List>&nbsp;summary&nbsp;=&nbsp;mapper.summaryScore(paras);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(summary);&nbsp;&nbsp;&nbsp;&nbsp;}}总之,直接使用mybatis,实现步骤还是相当的繁琐,效率太低。那换成mybatis plus的效果怎样呢?" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2"> <select&nbsp;id= "summaryScore"&nbsp;resultType= "map"&nbsp;parameterType= "cn.org.fluent.mybatis.springboot.demo.mapper.SummaryQuery">
&nbsp;&nbsp;&nbsp;&nbsp;select&nbsp;school_term,
&nbsp;&nbsp;&nbsp;&nbsp;subject,
&nbsp;&nbsp;&nbsp;&nbsp;count(score)&nbsp;as&nbsp;count,
&nbsp;&nbsp;&nbsp;&nbsp;min(score)&nbsp;as&nbsp;min_score,
&nbsp;&nbsp;&nbsp;&nbsp;max(score)&nbsp;as&nbsp;max_score,
&nbsp;&nbsp;&nbsp;&nbsp;avg(score)&nbsp;as&nbsp;max_score
&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;student_score
&nbsp;&nbsp;&nbsp;&nbsp; where&nbsp;school_term&nbsp;>=&nbsp; #{schoolTerm}
&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;subject&nbsp; in
&nbsp;&nbsp;&nbsp;&nbsp;<foreach&nbsp;collection= "subjects"&nbsp;item= "item"&nbsp;open= "("&nbsp;close= ")"&nbsp;separator= ",">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #{item}
&nbsp;&nbsp;&nbsp;&nbsp;</foreach>
&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;score&nbsp;>=&nbsp; #{score}
&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;is_deleted&nbsp;=&nbsp;0
&nbsp;&nbsp;&nbsp;&nbsp;group&nbsp;by&nbsp;school_term,&nbsp;subject
&nbsp;&nbsp;&nbsp;&nbsp;having&nbsp;count(score)&nbsp;>&nbsp; #{minCount}
&nbsp;&nbsp;&nbsp;&nbsp;order&nbsp;by&nbsp;school_term,&nbsp;subject
</select>

实现业务接口(这里是测试类, 实际应用中应该对应Dao类)

总之,直接使用mybatis,实现步骤还是相当的繁琐,效率太低。那换成mybatis plus的效果怎样呢?

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

3、换成mybatis plus实现效果

mybatis plus的实现比mybatis会简单比较多,实现效果如下

1b6b126e3d12410c9c65bbfb126d6528.jpeg

如红框圈出的,写mybatis plus实现用到了比较多字符串的硬编码(可以用Entity的get lambda方法部分代替字符串编码)。字符串的硬编码,会给开发同学造成不小的使用门槛,个人觉的主要有2点:

  1. 字段名称的记忆和敲码困难
  2. Entity属性跟随数据库字段发生变更后的运行时错误

其他框架,比如TkMybatis在封装和易用性上比mybatis plus要弱,就不再比较了

Part4 生成代码编码比较

4、fluent mybatis生成代码设置

5、mybatis plus代码生成设置

public&nbsp;class&nbsp;CodeGenerator&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;String&nbsp;dbUrl&nbsp;=&nbsp; "jdbc:mysql://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8";

&nbsp;&nbsp;&nbsp;&nbsp;@Test
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp; generateCode()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GlobalConfig&nbsp;config&nbsp;=&nbsp;new&nbsp;GlobalConfig();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataSourceConfig&nbsp;dataSourceConfig&nbsp;=&nbsp;new&nbsp;DataSourceConfig();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataSourceConfig.setDbType(DbType.MYSQL)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setUrl(dbUrl)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setUsername( "root")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setPassword( "password")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setDriverName(Driver.class.getName());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StrategyConfig&nbsp;strategyConfig&nbsp;=&nbsp;new&nbsp;StrategyConfig();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strategyConfig
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setCapitalMode( true)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setEntityLombokModel( false)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setNaming(NamingStrategy.underline_to_camel)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setColumnNaming(NamingStrategy.underline_to_camel)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setEntityTableFieldAnnotationEnable( true)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setFieldPrefix(new&nbsp;String[]{ "test_"})
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setInclude(new&nbsp;String[]{ "student_score"})
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setLogicDeleteFieldName( "is_deleted")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setTableFillList(Arrays.asList(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;TableFill( "gmt_create",&nbsp;FieldFill.INSERT),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;TableFill( "gmt_modified",&nbsp;FieldFill.INSERT_UPDATE)));

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setActiveRecord( false)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setIdType(IdType.AUTO)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setOutputDir(System.getProperty( "user.dir")&nbsp;+&nbsp; "/src/main/java/")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setFileOverride( true);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;AutoGenerator().setGlobalConfig(config)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setDataSource(dataSourceConfig)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setStrategy(strategyConfig)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setPackageInfo(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;PackageConfig()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setParent( "com.mp.demo")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setController( "controller")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setEntity( "entity")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;).execute();
&nbsp;&nbsp;&nbsp;&nbsp;}
}

Part5 FluentMybatis特性一览

6ddee78f035c693b1bb56e4ae4d4ad2d.jpeg

Part6三者对比总结

看完3个框架对同一个功能点的实现, 各位看官肯定会有自己的判断,笔者这里也总结了一份比较。

-Mybatis PlusFluent Mybatis代码生成生成 Entity生成Entity, 再通过编译生成 Mapper, Query, Update 和 SqlProviderGenerator易用性低高和Mybatis的共生关系需替换原有的SqlSessionFactoryBean对Mybatis没有任何修改,原来怎么用还是怎么用动态SQL构造方式应用启动时, 根据Entity注解信息构造动态xml片段,注入到Mybatis解析器应用编译时,根据Entity注解,编译生成对应方法的SqlProvider,利用mybatis的Mapper上@InsertProvider @SelectProvider @UpdateProvider注解关联动态SQL结果是否容易DEBUG跟踪不容易debug容易,直接定位到SQLProvider方法上,设置断点即可动态SQL构造通过硬编码字段名称, 或者利用Entity的get方法的lambda表达式通过编译手段生成对应的方法名,直接调用方法即可字段变更后的错误发现通过get方法的lambda表达的可以编译发现,通过字段编码的无法编译发现编译时便可发现不同字段动态SQL构造方法通过接口参数方式通过接口名称方式, FluentAPI的编码效率更高语法渲染特点无通过关键变量select, update, set, and, or可以利用IDE语法渲染, 可读性更高
更多推荐

Docker基础学习

Docker学习目标:掌握Docker基础知识,能够理解Docker镜像与容器的概念完成Docker安装与启动掌握Docker镜像与容器相关命令掌握TomcatNginx等软件的常用应用的安装掌握docker迁移与备份相关命令能够运用Dockerfile编写创建容器的脚本能够搭建与使用docker私有仓库​1Docke

Say0l的安全开发-代理扫描工具-Sayo-proxyscan【红队工具】

写在前面终于终于,安全开发也练习一年半了,有时间完善一下项目,写写中间踩过的坑。安全开发的系列全部都会上传至github,欢迎使用和star。工具链接地址https://github.com/SAY0l/Sayo-proxyscan工具简介SOCKS4/SOCKS4a/SOCKS5/HTTP/HTTPS快速代理扫描。后

【SpringCloud微服务全家桶学习笔记-服务注册zookeeper/consul】

SpringCloud微服务全家桶学习笔记Eureka服务注册gitee码云仓库9.其他服务注册框架(1)zookeeper安装与使用zookeeper需安装在虚拟机上,建议使用CentOS,安装地址如下:zookeeper镜像源选择第一个进入后下载tar包(第二个为源码文件,想研究源码可下载第二个)下载完成后使用xf

如果模块请求http改为了https,测试方案应该如何制定和修改?

当模块从HTTP切换到HTTPS时,需要制定相应的测试方案来验证系统的功能和安全性。以下是一些建议的测试内容和步骤:功能测试:a.确保模块能够正确地重定向到HTTPS端口。b.验证通过HTTPS访问模块时,是否能够正常加载和展示页面内容。c.检查模块的各种功能和业务逻辑是否能够正常工作。安全性测试:a.验证HTTPS证

小试GraphQL

之前做的需求,基本都是REST风格,以github提供的api为例,比较二者差异。试用GraphQL,找寻其独到之处RESTREST[1]一个URI代表一种资源通过HTTP动词对资源进行操作以创建一个仓库[2]为例GET[3],PATCH[4]和DELETE[5]类似GraphQLGraphQL的endpoint只有一

【ZLM】花屏现象记录

目录事后小结现象tcpdump看下包的情况移了两个摄像头到10.60.100.196事后小结花屏的现象,主要看链路时延的稳定性。如果ping-s2000ip,>2ms已经带宽2000*8*2/0.002s=16Mbps,说明带宽不够,应该接近100Mbps左右。你可以用5000的报文再测试一次。同时你可以试下与自己电脑

【数据结构复习之路】线性表(严蔚敏版)万字详解&主打基础

专栏:数据结构复习之路数据结构的三要数:逻辑结构、数据的运算、存储结构(物理结构)。我接下来要介绍的线性表,顾名思义也将从这三个大方向进行阐述:一、线性表的定义——逻辑结构线性表是具有相同数据类型的n(n>=0)个数据元素的有限序列,其中n为表长,当n=0时,线性表是一个空表。若用L命名线性表,则其一般表示为:⚠️线性

使用Python绘制多个股票的K线图

K线图是金融领域常用的技术分析工具,可以洞察地展示股票的开盘价、收盘价、最高价和最低价等信息。在投资决策中,对多个股票的走势进行对比分析是非常重要的。随着金融市场的发展,投资者对于多种股票的对比分析需求越来越高。传统的方式是通过查看多种股票的历史数据并手动对比图表,但这种方式效率低下很容易出错。随着互联网和数据分析技术

LVS+Haproxy

LVS+Haproxy一、Haproxy简介1.1、Haproxy应用分析1.2、Haproxy的特性1.3、常见负载均衡策略1.4、LVS、Haproxy、Nginx区别1.5、Haproxy的优点1.6、常见的Web集群调度器二、Haproxy部署实例四、日志定义优化一、Haproxy简介Haproxy是一个使用C

【学习笔记】C#基础 - 由C/C++衍生出来的面向对象的编程语言

一、程序结构1、基本语法usingSystem;//C#程序第一条语句都是usingSystem;//using关键字(可多个):在程序中包含命名空间namespaceRectangleApplication//namespace声明(可多个):包含一系列的类{classRectangle//class声明(可多个):

【个人笔记本】本地化部署 类chatgpt模型 详细流程

不推荐小白,环境配置比较复杂全部流程下载原始模型:Chinese-LLaMA-Alpaca-2linux部署llamacpp环境使用llamacpp将Chinese-LLaMA-Alpaca-2模型转换为gguf模型windows部署TextgenerationwebUI环境使用TextgenerationwebUI加

热文推荐