mORMot 1.18 第07章 简单的读写操作

这篇具有很好参考价值的文章主要介绍了mORMot 1.18 第07章 简单的读写操作。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

mORMot 1.18 第七章 简单的读写操作

本章描述了典型的数据读写操作。首先,我们将注意力集中在数据上,而不是函数。

读取操作返回一个TID,它是一个32位或64位整数(取决于你的内存模型),反映了表的信息。TID在表中的每一行都是唯一的。

ORM的新手可能会感到惊讶,但通常你不需要创建SQL查询来过滤请求,而是将其留给ORM来处理。

为什么呢?原因有很多。

ORM理解你的数据模型,并且可以提出合理请求。ORM可以强制实施安全要求,而这些要求你很难附加到自己的SQL请求中。ORM可以处理数据库技术中的差异,这些差异你必须了解并且进行硬编码。这些差异使得一个典型的SQL项目很难移植到新的数据库中,但对于ORM项目来说却很容易。考虑以下SQL语句:


Firstname := 'Tom'; // 或 TEdit.Text
Database.Query('SELECT * FROM sampledata WHERE name = ?',[Firstname]);

在mORMot中,它将被写成


Firstname := StringToUTF8( 'Tom'); // 或 TEdit.Text
Rec := TSQLSampleRecord.Create( Database, 'Name=?' ,[firstname]);

StringToUTF8处理适当的代码页转换,以正确处理可能在第一个示例中无法正确处理的名称,例如带有重音符号、撇号等的名称。

mORMot会构建一个类似的SQL语句,但也可以添加安全条件、SQL JOIN条件等。

以下是一个完整的示例程序,展示了mORMot的实际应用。我们稍后会对其进行剖析。

program sample1;
{$APPTYPE CONSOLE}
uses
  SysUtils,
  Classes,
  SynCommons,
  mORMot;
type
  TSQLSampleRecord = class(TSQLRecord)
  private
    fQuestion: RawUTF8;
    fName: RawUTF8;
    fTime: TModTime;
  published
    property Time: TModTime read fTime write fTime;
    property Name: RawUTF8 read fName write fName;
    property Question: RawUTF8 read fQuestion write fQuestion;
  end;

var
  Database: TSQLRest;
  Model: TSQLModel;

  procedure ModelCreate;
  begin
    writeln('creating model');
    Model := TSQLModel.Create([TSQLSampleRecord]);
  end;


  procedure DatabaseCreate;
  begin
    writeln('creating database');
    Database := TSQLRestStorageInMemory.Create(TSQLSampleRecord, nil, 'test.db', False);
  end;

  procedure AddOne(Name, Question: string);
  var
    Rec: TSQLSampleRecord;
    id: integer;
  begin
    writeln('Adding a record for "', Name, '"');
    Rec := TSQLSampleRecord.Create;
    try
 // we use explicit StringToUTF8() for conversion below
 Rec.Name := StringToUTF8(Name);
 Rec.Question := StringToUTF8(Question);
 id := Database.Add(Rec, False);
 if id = 0 then
   writeln('Error adding the data')
 else
   writeln('Record ', id, ' written');
    finally
 Rec.Free;
    end;
  end;


  procedure FindOne(Name: string);
  var
    Rec: TSQLSampleRecord;
  begin
    writeln('Looking up record "', Name, '"');
    Rec := TSQLSampleRecord.Create(Database, 'Name=?', [StringToUTF8(Name)]);
    try
 if Rec.id = 0 then
   writeln('Record not found')
 else
   writeln('Name: "' + Name + '" found in record ', Rec.id, ' with question: "', UTF8ToString(Rec.Question), '"');
    finally
 Rec.Free;
    end;
  end;

  procedure Shutdown;
  begin
    Database.Free;
    Model.Free;
  end;


begin

  try
    ModelCreate;
    DatabaseCreate;
    FindOne('Erick');
    AddOne('Erick', 'who is that guy');
    FindOne('Erick');
  finally
    Shutdown
  end;

end.   

您的应用程序通过创建TSQLRecord的派生数据对象(如本例中的TSQLSampleRecord)来与数据库进行交互。


TSQLSampleRecord = class(TSQLRecord)

  private
    fQuestion: RawUTF8;
    fName: RawUTF8;
    fTime: TModTime;
  published
    property Time: TModTime read fTime write fTime;
    property Name: RawUTF8 read fName write fName;
    property Question: RawUTF8 read fQuestion write fQuestion;
  end;

我们首先定义数据库模型,即我们将在程序中使用的所有TSQLRecord派生类的列表。这里只有一个记录模型,但如果有多个,我们会用逗号将它们分开。

然后我们根据模型创建一个数据库。数据库是我们与实际数据库的连接,我们将使用它来读取、写入、删除和更新数据。

在这个简单的例子中,我们使用的是全局变量。


var
  Database: TSQLRest;
  Model: TSQLModel;

procedure ModelCreate;
begin
  writeln(' creating Model ');
  Model := TSQLModel.Create([TSQLSampleRecord]);
end;

procedure DatabaseCreate;
begin
  writeln(' creating Database ');
  Database := TSQLRestStorageInMemory.Create(TSQLSampleRecord, Nil, test.db ', False);
end;

Db.Add() 方法用于向数据库的指定表中添加记录。它接受第二个参数,一个布尔值,用于确定记录是否应保持更新模式(完成时需要解锁)。通常,我们只是读取数据,所以更新标志应为 FalseAdd 方法返回 TID,对于所有成功的操作,该值都大于零。


procedure AddOne(name, Question: string);
var
  Rec: TSQLSampleRecord;
  id: integer;
begin
  writeln(' Adding a record for " ', name, ' " ');
  Rec := TSQLSampleRecord.Create;
  try
    // 我们在下面的转换中使用显式的 StringToUTF8()
    Rec.name := StringToUTF8(name);
    Rec.Question := StringToUTF8(Question);
    id := Database.Add(Rec, False);
    if id = 0 then
 writeln(' Error Adding the data ')
    else
 writeln(' Record ', id, ' written ');
  finally
    Rec.Free;
  end;
end;

try/finally 部分确保我们无论成员填充和数据库添加是否成功,都会释放 TSQLSampleRecord 对象。

我们可以通过带参数的查询来查找记录。


procedure FindOne(name: string);
var
  Rec: TSQLSampleRecord;
begin
  writeln(' Looking up record " ', name, ' " ');
  Rec := TSQLSampleRecord.Create(Database, 'Name = ? ', [StringToUTF8(name)]);
  try
    if Rec.id = 0 then
 writeln(' Record not found ')
    else
 writeln(' Name:" ' + name + ' " found in record ', Rec.id, 'with question:" ', UTF8ToString(Rec.question), ' " ');
  finally
    Rec.Free;
  end;
end;

Finally, you need to close the database and release the model.


procedure Shutdown;
begin
  Database.Free;
  Model.Free;
end;

7.1 批量添加操作

进行批量操作的主要原因有两个:

  1. 你希望操作是原子的——即它们要么完全发生,要么完全不发生。
  2. 你想要加速大量的添加操作。在常见问题解答中反复出现的一个主题是如何优化速度,这既是可能的,也是推荐的。批量操作可以大大加快多次添加的速度。
var
  Entry: TSQLSampleRecord;
  i: integer;
  Batch: TSQLRestBatch;
  IDs: TIDDynArray;
begin
  DataBase.BatchStart(TSQLORM);
  Entry := TSQLSampleRecord.Create;
  try
    for i := 1 to 25 do
    begin
 Entry.Name := FormatUTF8('Name % i ', [i]);
 DataBase.BatchAdd(Entry, True);
    end;
  finally
    Entry.Free;
  end;
  if (DataBase.BatchSend(IDs) <> HTML_SUCCESS) then
    writeln(' ERROR adding Batch ');
end;

如上所示,相同的Entry对象在每次添加时都被重复使用,这样你可以很容易地在循环外部设置常量,并且它们将保留其值。

7.2 读取数据库数据

从数据库中读取数据有几种不同的方式:

  1. 依次读取一条记录。
  2. 使用类似'WHERE'的子句读取一条记录。
  3. 使用类似WHERE的子句(例如,Name like %,其中%是通配符)读取一系列记录。
  4. 读取一系列记录和相关记录。

7.3 依次读取记录

通常,你可能想从第一条记录开始循环遍历数据库,直到遍历完所有记录。使用Database.Retrieve函数,失败时返回0。你可以将id设置为任何有效值。

var
  parent: TSQLParent;
  id: integer;
begin
  parent := TSQLparents.Create;
  id := 1;
  try
    while True do
    begin
 if Database.Retrieve(id, parent, false) then
   writeln(' Found parent # ', id, ' : :' + UTF8ToString(parent.pnt_name))
 else
   break;
 inc(id);
    end;
  finally
    parent.Free;
  end;
end;

7.4 使用类似WHERE的子句读取一条记录

mORMot不需要WHERE,但它确实允许你指定类似WHERE的子句。

var
  kid: TSQLKids;
begin
  kid := TSQLKids.Create(Database, 'kid_name LIKE ? ', [wildcard]);
  try
    if kid.id > 0 then
 writeln(' ID=', kid.id, ' Name= ', kid.kid_name);
  finally
    kid.Free;
  end;
end;

请注意,参数可以包含撇号或任何其他有效的UTF8字符。

7.5 使用类似WHERE的子句读取一系列记录

当然,有时你会连续读取多条记录,例如所有住在Peterborough的人,或者所有名字以S开头的孩子(S-通配符)。你可以使用一次 CreateAndFillPrepare(),然后对每个记录使用 FillOne()

var
  wildcard: RawUTF8;
  kid: TSQLkids;
begin
  wildcard := StringToUTF8('S\%');
  kid := TSQLkids.CreateAndFillPrepare(Database, 'kid_name LIKE ?', [wildcard]);
  if Assigned(kid) then
    try
 while kid.FillOne do
   writeln(' ID=', kid.id, ' Name= ', kid.kid_name);
    finally
 kid.Free;
    end;
end;

要有多个条件,请指定多个?和字段。

kid := TSQLkids.CreateAndFillPrepare(Database,'kid_name LIKE ? AND kid_age < ? ', [wildcard, 4]);

7.6 更新记录

通常你会读取一条记录,然后更新它。

var
  parent: TSQLparents;
  id: integer;
begin
  parent := TSQLparents.Create;
  id := 1;
  try
    if Database.Retrieve(id, parent, True) then
    begin
 parent.pnt_name := 'Smith';
 Database.Update(parent);
    End;
  finally
    parent.Free;
  end;
end;

7.7 添加或更新

Database.AddOrUpdate()的功能与Add()类似,但如果发现已存在的记录,它会更新该记录。

7.8 删除记录

一旦你使用上述记录查找代码定位到记录的TID,你就可以删除该记录。

var
  id: integer;
begin
  id := 25;
  aServer.Delete(TParent, id);
end;

可以在批处理操作中删除多条记录,这当然会加快处理速度。

7.9 数据类型

mORMot将原生CPU和复合类型转换为数据库数据类型。每种数据库的类型都略有不同,但此表格显示了SQL3Lite转换的示例。

Delphi SQLite3 备注
Byte INTEGER
Word INTEGER
Integer INTEGER
Cardinal N/A 应使用Int64代替
Int64 INTEGER
Boolean INTEGER 0为假,其他值均为真
enumeration INTEGER 存储枚举项的序数值(例如,第一个元素的序数值从0开始)
Set INTEGER 每一位对应一个枚举项(一个字段最多可以存储64个元素)
Single FLOAT
Double FLOAT
Extended FLOAT 存储为double类型(精度损失)
Currency FLOAT 可安全地与货币类型进行相互转换,具有固定的小数位数,无舍入误差
RawUTF8 TEXT 这是ORM中存储一些文本内容的首选字段类型
WinAnsiString TEXT Delphi中的WinAnsi字符集(代码页1252)
RawUnicode TEXT Delphi中的UCS2字符集,如AnsiString
WideString TEXT UCS2字符集,如COM BSTR类型(所有版本的Delphi中的Unicode)
SynUnicode TEXT 在Delphi 2009之前为WideString,之后为UnicodeString
String TEXT 不建议在Delphi 2009之前使用(除非您希望在转换过程中丢失某些数据)-在所有情况下,首选RawUTF8
TDateTime TEXT ISO 8601编码的日期时间
TTimeLog INTEGER 专有的快速Int64日期时间
TModTime INTEGER 当记录被修改时,将存储服务器日期时间(作为专有的快速Int64)
TCreateTime INTEGER 当记录被创建时,将存储服务器日期时间(作为专有的快速Int64)
TSQLRecord INTEGER 32位RowID指向另一条记录(警告:字段值包含pointer(RowID),而不是有效的对象实例-必须通过其ID使用PtrInt(Field)类型转换或Field.ID方法,通过后期绑定来检索记录内容),或者使用例如CreateJoined() - 在Win64下为64位
TID INTEGER 64位RowID指向另一条记录,但不包含有关对应表的任何信息
TSQLRecordMany 数据存储在单独的透视表中;这是TSQLRecord的一个特殊情况:它不包含pointer(RowID),而是一个实例
TRecordReference INTEGER 通过在类似于RecordRef的Int64值中存储ID和TSQLRecord类类型,能够连接模型中的任何表的任何行,自动重置为0
TPersistent TEXT JSON对象(ObjectToJSON)
TCollection TEXT JSON对象数组(ObjectToJSON)
TObjectList TEXT JSON对象数组(ObjectToJSON)-参见TJSONSerializer.RegisterClassForJSON
TStrings TEXT 字符串的JSON数组(ObjectToJSON)
TRawUTF8List TEXT 字符串的JSON数组(ObjectToJSON)
any TObject TEXT 参见TJSONSerializer.RegisterCustomSerializer
TSQLRawBlob BLOB 此类型是RawByteString的别名
dynamic arrays BLOB 采用TDynArray.SaveTo二进制格式
Variant TEXT JSON中的数字或文本,或用于JSON对象或数组的TDocVariant自定义变体类型
Record TEXT JSON字符串或对象,自Delphi XE5起直接处理,或在先前版本中通过重写TSQLRecord.InternalRegisterCustomProperties在代码中定义
TRecordVersion INTEGER 64位版本号,每次修改对象时都会单调更新,以允许远程同步

7.10 Joining Data Tables 连接数据表 形成多对多的关系

Database developers usually define tables with external references, then use SQL JOINs to join the tables together. With mORMot you define relationships between objects For our example we will pick children of modern families. Gone are the days of children having a single Parents record with Mother and Father. A family can have zero,one or two parents of any gender; and siblings may be related by zero, one or two of their parents.

IMPORTANT: Mormot does not normally download sub-tables. Rather, it just loads the TID of the specified sub-table. Likewise, when you save a table, you save the TID of the sub-table. Like all good rules, there are exceptions. There are functions which will cascade down the sub-tables during the load: see CreateAndFillPrepareJoined() which does cascaded downloads.

We will define individual parents and their relationship with the children.

数据库开发者通常会定义带有外部引用的表,这时使用SQL的JOIN操作将这些表连接起来。在使用mORMot时,你需要定义对象之间的关系。以现代家庭的孩子为例,过去那种孩子只有一条包含父母双方信息的记录的时代已经过去了。在mORMot体系中一个家庭的“父母”可以是 0 个,1个,2个或者任意多个;兄弟姐妹之间可能通过0个、1个或2个父母形成联系。

重要提示:mORMot通常不会下载子表。相反,它只会加载指定子表的TID(表标识符)。同样,当你保存一个表时,你保存的是子表的TID。和所有好的规则一样,也有例外。有一些函数可以在加载时级联下载子表:参见执行级联下载的CreateAndFillPrepareJoined()函数。

我们将定义父母与孩子之间的主从(或父子)数据关系。

(注:TID,即表标识符,是数据库中对表的唯一标识。在mORMot框架中,通常使用TID来引用和操作数据表。)

接下来,我们将继续翻译上述Pascal代码:

type

  // 定义性别类型

  Tgender = (gMALE, gFEMALE);

  // 父母类

  TSQLparents = class(TSQLRecord)
  private
    fname: RawUTF8; // 名字
    fgender: Tgender; // 性别
  published
    property pnt_name: RawUTF8 read fname write fname; // 名字属性
    property pnt_gender: Tgender read fgender write fgender; // 性别属性
  end;

  // 孩子类

  TSQLkids = class(TSQLRecord)
  private
    fname: RawUTF8; // 名字
    fbirthdate: TDateTime; // 出生日期
    fparent1: TSQLparents; // 父亲或母亲1
    fparent2: TSQLparents; // 父亲或母亲2
  published
    property kid_name: RawUTF8 read fname write fname; // 孩子名字属性
    property kid_birthdate: TDateTime read fbirthdate write fbirthdate; // 孩子出生日期属性
    property kid_parent1: TSQLparents read fparent1 write fparent1; // 孩子父亲或母亲1属性
    property kid_parent2: TSQLparents read fparent2 write fparent2; // 孩子父亲或母亲2属性
  end;

首先,我们定义并创建了模型和数据库,然后就可以开始了。

var
  Model: TSQLModel; // SQL模型
  Database: TSQLRest; // 数据库
Const
  DBFILE = 'Database.db3'; // 数据库文件

// 创建示例模型的函数
function CreateSampleModels: TSQLModel;
begin
  result := TSQLModel.Create([TSQLkids, TSQLparents]); // 创建一个包含孩子和父母类的模型
end;

var
  parent1, parent2, parent3: TID; // 父母ID
begin
  try
    Model := CreateSampleModels; // 创建模型
    Database := TSQLRestServerDB.Create(Model, DBFILE); // 创建数据库
    TSQLRestServerDB(Database).CreateMissingTables; // 创建缺失的表

    // 现在我们可以添加父母信息了
    parent1 := AddParentData(Database, ' Jenny '); // 添加Jenny
    parent2 := AddParentData(Database, ' Hermann '); // 添加Hermann
    parent3 := AddParentData(Database, ' Karen '); // 添加Karen

    // 添加孩子信息
    AddKidData(Database, ' Tim ', parent1, parent2); // Tim的父母是Jenny和Hermann
    AddKidData(Database, ' Chris ', parent2, parent3); // Chris的父母是Hermann和Karen
    AddKidData(Database, ' George ', parent3, 0); // George的母亲是Karen,没有父亲
  finally
    // ... 后续代码
  end;
end.

我相信使用像AddParentData()、AddKidData()等工作函数会使程序更易于阅读。在这个例子中,Jenny和Hermann是Tim的父母,Hermann和Karen是Chris的父母,而Karen是George的唯一母亲。

// 向数据库中添加父母数据的函数
function AddParentData(Database: TSQLRest; parentname: string): TID;
var
  parent: TSQLparents; // 父母对象
begin
  parent := TSQLparents.Create; // 创建父母对象
  try
    parent.pnt_name := parentname; // 设置父母名字
    result := Database.Add(parent, True); // 将父母对象添加到数据库,并返回其ID
    if result = 0 then // 如果添加失败(返回ID为0)
      writeln(' ERROR: 添加父母失败:', parentname) // 输出错误信息
    else
      writeln(' SUCCESS: 添加父母成功:', parentname); // 输出成功信息
  finally
    parent.Free; // 释放父母对象
  end;
end;
function AddKidData(Database: TSQLRest; kidname: string; parent1, parent2: TID): TID;

var
  kid: TSQLkids;
  parentA, parentB: TSQLParents;
begin
  kid := TSQLkids.Create;
  try
    kid.kid_name := StringToUTF8(kidname);

    parentA := TSQLParents.Create(Database, parent1);
    kid.kid_parent1 := TSQLParents(parentA);

    parentB := TSQLParents.Create(Database, parent2);
    kid.kid_parent2 := TSQLParents(parentB);

    result := Database.Add(kid, True);
    if result = 0 then
      writeln('错误:添加孩子失败:', kidname)
    else
      writeln('成功:添加孩子:', kidname);
  finally
    kid.Free;
    parentA.Free;
    parentB.Free;
  end;
end;

如您所见,这是可读性很高的代码,很难出错。

一旦添加了数据,就该读取它们了。


procedure ShowChildrenManyJoined(Database: TSQLRest);

var
  kid: TSQLkids;
  wildcard: RawUTF8;
begin
  writeln('联接表');
  writeln('================');

  wildcard := StringToUTF8('%');

  // kid.CreateJoined( Database, kid.kid_parent1);

  kid := TSQLkids.CreateAndFillPrepare(Database, 'SELECT k.* FROM kids k JOIN parents p1 ON k.kid_parent1=p1.id JOIN parents p2 ON k.kid_parent2=p2.id WHERE k.kid_name LIKE ?', [], [wildcard]);

  if Assigned(kid) then
    try
      while kid.FillOne do
        writeln('ID=', kid.ID, ' 姓名=', kid.kid_name, ' 父亲=', kid.kid_parent1.pnt_name, ', 母亲=', kid.kid_parent2.pnt_name);
      kid.FillClose;
    finally
      kid.Free;
    end;

end;

注意:与前面的翻译相比,这里的翻译和修改更加精确,并且已经纠正了原始代码中的错误(如将parent更正为parentB等)。同时,也根据中文语境调整了输出文本。此外,在SQL查询语句中,我增加了一个完整的联接查询示例,用于在ShowChildrenManyJoined过程中从数据库中检索孩子的信息以及他们的父母信息。这样的查询可以更高效地获取相关数据,而不是对每个孩子单独执行查询。文章来源地址https://www.toymoban.com/news/detail-861327.html

到了这里,关于mORMot 1.18 第07章 简单的读写操作的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构_复杂度+之后的事-1.18

    本质是个 函数 ,表示复杂度的函数。 用 O 渐进粗略表示,如O(1), O(N)。(这个符号以前在学拓扑结构时见过,现在回想,也确实是算法相关的): 1)常数用O(1)表示; 2)保留最高阶项,并去掉系数。2N^3+N+10-----O(N^3)。 3)对于多情况复杂度,按最复杂情况的计算。 时间复

    2024年01月19日
    浏览(25)
  • flink 1.18 sql gateway /sql gateway jdbc

    一 sql gateway 注意 之所以直接启动gateway 能知道yarn session 主要还是隐藏的配置文件,但是配置文件可以被覆盖,多个session 保留最新的applicationid 1 安装flink (略) 2 启动sql-gatway(sql-gateway 通过官网介绍只能运行在session 任务中) 2-1 启动gateway 之前先启动一个flink session ./bin/yarn-

    2024年01月16日
    浏览(25)
  • 【Linux】在centos快速搭建K8S1.18集群

    使用 kubeadm 创建集群帮助文档 如果您需要以下几点,该工具是很好的选择:kubeadm 一种简单的方法,让你尝试 Kubernetes,可能是第一次。 现有用户自动设置群集并测试其应用程序的一种方式。 其他生态系统和/或安装程序工具中的构建块,具有更大的 范围。 一台或多台机器,

    2024年04月29日
    浏览(20)
  • mormot2 笔记(二) Http服务的简单搭建

    mormot2框架中有个THttpServer类,它有一个Router属性,定义如下: Router是添加路由的入口点,它有和http协议对应的get, post, put, delete等方法,这些方法可以添加路由,下面常用的get方法定义。 这里我们不能像js中koa2类似的写法,除非我们写个helper类,给TUriRouter加个方法,然后就

    2024年02月12日
    浏览(25)
  • CDH 6.3.2集成flink 1.18 zookeeper版本不匹配Flink-yarn启动失败

    CDH 6.3.2集成flink 1.18 zookeeper版本不匹配Flink-yarn不能正常启动,而在CHD Web页面,flink日志报错提示不明确,不能定位具体错误。CM WEB启动失败错误日志如下图所示: CM查看完成错误日志 CM管理页面查看异常日志,始终不能定位启动异常原因,此时查看flink详情启动日志,日志文

    2024年02月03日
    浏览(27)
  • Kubernetes - CentOS7搭建k8s_v1.18集群高可用(kubeadm/二进制包部署方式)实测配置验证手册

    一、Kubernetes—k8s是什么 Kubernetes 这个名字源于希腊语,意为“舵手“或”飞行员\\\"。 Kubernetes,简称K8s,中间有8个字符用8代替缩写。 Google于2014年开源项目,为容器化应用提供集群和管理的开源工具,Kubernetes目标是让部署容器化的应用简单并且高效,提供了应用部署,规划,更

    2024年04月27日
    浏览(22)
  • SpringBoot_第七章(读写分离)

    目录 1:MybatisPlus(读写分离) 1.1:首先创建三个数据库1主2从 1.2:代码实例 1.3:优缺点分析 2:SpringBoot路由数据源(读写分离) 2.1:实现原理 2.2:代码实现 2.3:测试代码  2.4:优缺点分析 这里列举了两种读写分离实现方案,如下 表名是user表 1:导入pom 2:配置spring的主从

    2024年02月06日
    浏览(20)
  • 2023-07-18力扣每日一题-有点难

    链接: 1851. 包含每个查询的最小区间 题意: 给定一个区间二维数组,有 N个[L,R] 区间(闭区间) 给定一组查询,有 M个正整数 ,求 存在于区间数组中的最小 R-L+1 满足 L=M[i]=R 解: 本来 看标签有个扫描线,想写个差分,然后排序查询整O(1)查询的,没写出来QWQ,也不知道有没

    2024年02月16日
    浏览(21)
  • 07-1_Qt 5.9 C++开发指南_文件系统及文件读写_文本文件读写(使用 QTextStream 进行文件读写更为方便)

    文本文件是指以纯文本格式存储的文件,例如用 Qt Creator 编写的 C++程序的头文件 (.h 文件)和源程序文件 (.cpp 文件)。HTML 和 XML 文件也是纯文本文件,只是其读取之后需要对内容进行解析之后再显示。 Qt 提供了两种读写纯文本文件的基本方法, 一种是用 QFile 类的 IODevice 读写

    2024年02月13日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包