初始kbmmw 中的ORM

在kbmmw 5.02.1 中,加入了ORM 的功能(这里可能和其他语言的定义不完全一样),我们就简单的认为

它就是一个类与数据库的转换吧。今天就先介绍一下如何通过kbmmw 的ORM 功能,实现类与数据库的相互

转换和操作。

前提条件:delphi 10.2.1

kbmmw 5.02.1

unidac 7.0.2

haosql for sql server 2008  非常不错的一个sql 管理器

启动haosql  for sqlserver2008 管理器,启动数据库。

打开delphi ,建立一个标准的工程,放置如图的几个控件

设置uniconnection1 连接sql server 2008 数据库

ok

加入几个必要的单元,并设置好初始化代码。

unit mainp;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  kbmMWORM, Vcl.StdCtrls, Data.DB, DBAccess, Uni, kbmMWCustomConnectionPool,
  kbmMWCustomSQLMetaData, kbmMWMSSQLMetaData, kbmMWUniDAC, UniProvider,
  SQLServerUniProvider, DASQLMonitor, UniSQLMonitor ;

type
  TForm2 = class(TForm)
    kbmMWUNIDACConnectionPool1: TkbmMWUNIDACConnectionPool;
    kbmMWMSSQLMetaData1: TkbmMWMSSQLMetaData;
    UniConnection1: TUniConnection;
    Button1: TButton;
    SQLServerUniProvider1: TSQLServerUniProvider;
    UniSQLMonitor1: TUniSQLMonitor;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    ORM:TkbmMWORM;
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject);
begin
  ORM:=TkbmMWORM.Create(kbmMWUNIDACConnectionPool1); // 建立ORM 对象
  ORM.QueryMode:=mwoqmMixed;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  ORM.Free; // 释放ORM对象
end;

end.

现在新建一个单元,定义一个联系人类,并加入对应的标注信息

unit uContact;

interface
uses  System.Generics.Collections,kbmMWNullable,kbmMWRTTI,  kbmMWORM,DB;

type

    [kbmMW_Table(‘name:CONTACT‘)] // 表名为 contact
     TContact = class
     private
        FID:kbmMWNullable<string>;
        FName:kbmMWNullable<string>;
        FAddress:kbmMWNullable<string>;
        FZipCode:kbmMWNullable<string>;
        FCity:kbmMWNullable<string>;
        FComments:kbmMWNullable<string>;
       public
        [kbmMW_Field(‘primary:true, generator:shortGuid‘,ftString,40)] //主键,并自动生成为GUID
        property ID:kbmMWNullable<string> read FID write FID;
        [kbmMW_Field(‘name:NAME‘,ftString,50)]
        property Name:kbmMWNullable<string> read FName write FName;
        [kbmMW_Field(‘name:ADDRESS‘,ftString,80)]
        property Address:kbmMWNullable<string> read FAddress write FAddress;
        [kbmMW_Field(‘name:ZIPCODE‘,ftInteger)]
        property ZipCode:kbmMWNullable<string> read FZipCode write FZipCode;
         [kbmMW_Field(‘name:city‘,ftString,50)]
        property City:kbmMWNullable<string> read FCity write FCity;
        [kbmMW_Field(‘name:comments‘,ftString,200)]
        property Comments:kbmMWNullable<string> read FComments write FComments;
       end;

implementation

initialization
   TkbmMWRTTI.EnableRTTI([TContact]); //开启RTTI
   kbmMWRegisterKnownClasses([TContact]);//注册 对象

end.

好了,我们返回主窗体, 加入对应的代码,我们先建立对应的表。

procedure TForm2.Button1Click(Sender: TObject);
begin

 ORM.CreateTable([Tcontact]);

end;

编译运行,点创建库 按钮,显示建表成功。

我们看看背后发生了什么?首先我们先在 sql monitor 里面,看看后台做了什么?

通过sql monitor, 我们可以非常清晰的看见,kbmmw 先在次数据库中查询是否有这个表,如果没有这个表,则根据Tcontact 中定义的

字段来生成对应的SQL 语句,执行这个SQL,在数据库中生成对应的表。

数据库中生产的完全没问题。我们下一步生成一些数据,看看是否正常。

生成数据代码

procedure TForm2.Button3Click(Sender: TObject);
var
   t1,t2,t3:TContact ;
begin

   t1:=TContact.Create;
   t1.Name:=‘红鱼儿‘;
   t1.Address:=‘不告诉你‘;
   t1.ZipCode:=‘1234567‘;
   t1.City:=‘四平‘;
   t1.Comments:=‘老牌程序猿‘;

   ORM.Persist(t1);

   t2:=TContact.Create;
   t2.Name:=‘努力的干‘;
   t2.Address:=‘还是不告诉你‘;
   t2.ZipCode:=‘54565552‘;
   t2.City:=‘泸州‘;
   t2.Comments:=‘变形金刚制造者‘;

   ORM.Persist(t2);

   t3:=TContact.Create;
   t3.Name:=‘清幽傲竹‘;
   t3.Address:=‘就是不告诉你‘;
   t3.ZipCode:=‘252556‘;
   t3.City:=‘福州‘;
   t3.Comments:=‘真的很帅的!‘;

   ORM.Persist(t3);

  showmessage(‘操作成功‘);

end;

看看后台都有那些sql.实际上这个Persist 是更新和插入,如果更新失败就插入。

看看数据库里面的生成数据的效果。

完全正确。

下面看一下如何通过ORM 查询数据。

kbmmw orm 查询数据有三种方式。

// Query mode controls what syntax to use for queries.
   // mwoqmMW (default) use kbmMW‘s SQL syntax and automatically
   //   rewrite the query to match supported databases.
   // mwoqmNative provides the query string without alterations to the
   //   database.
   // mwoqmMixed default use kbmMW‘s SQL syntax with automatic rewrite
   //   unless the first character in the query statement is #
   TkbmMWORMQueryMode = (mwoqmMW,mwoqmNative,mwoqmMixed);

缺省使用kbmmw 自身的SQL 语法,并自动转换成对应的数据库语法

第二种是直接使用目标数据库的语法

第三种是混合方式, 如果查询首字母不是# 的话,就用kbmmw 自身的sql 语法。

我们使用混合模式查询

procedure TForm2.Button5Click(Sender: TObject);
var
   o:TObjectList<Tcontact>;
begin
     o:=TObjectList<Tcontact>(orm.Query(Tcontact,‘#SELECT * FROM contact‘,true));

     showmessage(‘共有‘+o.Count.ToString +‘条记录‘);

     o.Free;

end;

或者

procedure TForm2.Button5Click(Sender: TObject);
var
   o:TObjectList<Tcontact>;
begin
     o:=orm.QueryList<Tcontact>(‘#SELECT * FROM contact‘);
     showmessage(‘共有‘+o.Count.ToString +‘条记录‘);
     o.Free;
end;

运行结果

后台SQL 亦是如此

我们来查询单条数据,单挑数据有两种查询方式

一种是SQL 方式,一种ORM 方式

先介绍一下sql 方式

procedure TForm2.Button6Click(Sender: TObject);
var
   o:Tcontact;
begin
     o:=orm.Query<Tcontact>(‘#SELECT * FROM contact WHERE NAME=‘‘红鱼儿‘‘‘);

     if o=nil then
        begin
          showmessage(‘没有查询到数据!‘);
          exit;
        end;

     showmessage(o.Comments);

     o.Free;

end;

运行效果

使用kbmw ORM 方式查询

procedure TForm2.Button7Click(Sender: TObject);
var
   o:Tcontact;
   b:boolean;
begin
     o:=orm.Query<Tcontact>([‘name‘],[‘红鱼儿‘],mwoqoEQ);
     if o=nil then
         begin
          showmessage(‘没有查询到数据!‘);
          exit;
        end;
      showmessage(o.Comments);
     o.Free;

end;

运行结果

修改数据库

procedure TForm2.Button8Click(Sender: TObject);
var
   o:Tcontact;

begin
     o:=orm.Query<Tcontact>([‘name‘],[‘红鱼儿‘],mwoqoEQ);
     if o=nil then
         begin
          showmessage(‘没有查询到数据!‘);
          exit;
        end;

    o.Name:=‘红鱼儿二代‘;
    orm.Update(o);

      showmessage(‘修改成功!‘);
     o.Free;

end;

结果也一切正常

看看后台发生了什么?

数据库是否保存正确?

没问题,太爽了。

顺便添加一下删除的代码

procedure TForm2.Button9Click(Sender: TObject);
var
   o:Tcontact;

begin
     o:=orm.Query<Tcontact>([‘name‘],[‘红鱼儿‘],mwoqoEQ);
     if o=nil then
         begin
          showmessage(‘没有查询到数据!‘);
          exit;
        end;

    orm.Delete(o);

      showmessage(‘删除成功!‘);
     o.Free;

end;

清除全部的数据

procedure TForm2.Button4Click(Sender: TObject);
begin
      orm.PurgeTable(Tcontact);

end;

删除建的表

procedure TForm2.Button2Click(Sender: TObject);
begin
   ORM.DeleteTable([Tcontact])
end;

终于写完了。

大家对上面kbmmw 标注肯定很头疼,第一要记很多标注名,第二不能笔误,这个确实麻烦,

好消息是,作者已经把自动生产这些标注列入计划,期待后面的版本能直接自动生产,那就方便多了。

在没有自动声场之前,请大家参照一下说明,自己手工处理。

// ORM attribute syntax
// ====================
//
// kbmMW_Table - Define a table.
//   Must be used on classes.
//
//   Define a table named person.
//   [kbmMW_Table(‘name:person‘)]
//
//   Define 2 ascending indexes i_fieldname, and i_anotherfieldname on the field fieldname and anotherfieldname.
//   [kbmMW_Table(‘name:person, index:fieldname, index:anotherfieldname...
//
//   Define an ascending index named i1, on the field name
//   [kbmMW_Table(‘name:person, index:{name:i1,field:name},...
//
//   Define a descending index named i1, on the field name
//   [kbmMW_Table(‘name:person, index:{name:i1,field:name,descending:true},...
//
//   Define a compound unique index named i2, on the fields name and age. Name field part is descending.
//   [kbmMW_Table(‘name:person, index:{name:i2,unique:true,fields:[{name:name,descending:true},{name:age}]
//
//
// kbmMW_Field - Define fields in a table.
//   Must be used on properties within a class if they are to be persisted.
//
//   Define a field that will be persisted. Its type will be decided for
//     from the property type. String type fields will have a size of 50.
//     Table field name will be the same as the property name.
//   [kbmMW_Field]
//
//   Define a field that will be persisted. It will accept unicode data of max 50 characters.
//     It will have the same name as the property.
//   [kbmMW_Field(ftWideString,50)]
//
//   Define a field named id, and make it primary key. It will be automatically populated bu the generator shortGuid.
//   [kbmMW_Field(‘name:id, primary:true, generator:shortGuid‘,ftString,40)]
//   property ID:kbmMWNullable<string> read FID write FID;
//
//   These generators exists:
//     GUID           - Returns a GUID formatted as a regular GUID {123e4567-e89b-12d3-a456-426655440000}
//     SHORTGUID      - Returns a short GUID where braces and dashes are missing: 123e4567e89b12d3a456426655440000
//     SEQUENCE       - Returns next unique number from a sequence. Provide name of sequencer in sequence property
//                      and optional sequencestart property (not supported by all databases!)
//     DATETIME       - Returns a date time value, formatted according to the dateFormat property.
//
//   Define a field named id, and make it primary key. It will be populated by a sequence generator.
//     Since no sequencer was given, one is automatically generated named s_tablename_fieldname
//   [kbmMW_Field(‘name:id, primary:true, generator:sequence‘,ftInteger)]
//   property ID:kbmMWNullable<integer> read FID write FID;
//
//   Define a field named id, and make it primary key. It will be populated by sequence generator SEQ, starting from value 10.
//     (not all databases supports sequencers with a defined start!)
//   [kbmMW_Field(‘name:id, primary:true, generator:sequence, seqneuce:SEQ1, sequenceStart:10‘,ftInteger)]
//   property ID:kbmMWNullable<integer> read FID write FID;
//
//   Define a field named id, and make it primary key. It will be populated automatically by the database.
//     (not all databases support auto increment type fields!)
//   [kbmMW_Field(‘name:id, primary:true‘,ftAutoInc)]
//   property ID:kbmMWNullable<integer> read FID write FID;
//
//   Define a field named datetime containing date/time values as Delphi local time values.
//   [kbmMW_Field(‘name:datetime‘,ftDateTime)]
//   property DateTime:TkbmMWDateTime read FDateTime write FDateTime;
//
//   Define a field named datetime containing date/time values as Delphi UTC values.
//   [kbmMW_Field(‘name:datetime, dateFormat:UTC‘,ftDateTime)]
//   property DateTime:TkbmMWDateTime read FDateTime write FDateTime;
//
//   Define a field named datetime containing date/time values as Unix local time millisecs since EPOC.
//   [kbmMW_Field(‘name:datetime, dateFormat:LOCALSINCEEPOCHMS‘,ftInt64)]
//   property DateTime:TkbmMWDateTime read FDateTime write FDateTime;
//
//   Define a field named datetime containing date/time values as Unix UTC time millisecs since EPOC.
//   [kbmMW_Field(‘name:datetime, dateFormat:UTCSINCEEPOCHMS‘,ftInt64)]
//   property DateTime:TkbmMWDateTime read FDateTime write FDateTime;
//
//   Define a field named datetime containing date/time values as Unix local time secs since EPOC.
//   [kbmMW_Field(‘name:datetime, dateFormat:LOCALSINCEEPOCH‘,ftInt64)]
//   property DateTime:TkbmMWDateTime read FDateTime write FDateTime;
//
//   Define a field named datetime containing date/time values as Unix UTC time secs since EPOC.
//   [kbmMW_Field(‘name:datetime, dateFormat:UTCSINCEEPOCH‘,ftInt64)]
//   property DateTime:TkbmMWDateTime read FDateTime write FDateTime;
//
//   Define a field named datetime containing date/time values as ISO8601 formatted string.
//   [kbmMW_Field(‘name:datetime, dateFormat:ISO8601‘,ftString,50)]
//   property DateTime:TkbmMWDateTime read FDateTime write FDateTime;
//
//   Define a field named datetime containing date/time values as RFC1123 formatted string.
//   [kbmMW_Field(‘name:datetime, dateFormat:RFC1123‘,ftString,50)]
//   property DateTime:TkbmMWDateTime read FDateTime write FDateTime;
//
//   Define a field named datetime containing date/time values as NCSA formatted string.
//   [kbmMW_Field(‘name:datetime, dateFormat:NCSA‘,ftString,50)]
//   property DateTime:TkbmMWDateTime read FDateTime write FDateTime;
//
// kbmMW_Null - Specify NULL conversion.
//   (This attribute is also used for object marshalling).
//
//   If, for example, a property is of type integer, the property is not directly able to indicate a NULL state since
//   all values of an integer are considered non NULL values.
//   However its possible to define a specific value to be interpreted as NULL.
//   Eg.
//   [kbmMW_Field(‘name:somefield‘,ftInteger)]
//   [kbmMW_Null(-1)]
//   property MyProperty:integer read FMyProperty write FMyProperty;
//
//   This will define that the value -1 must be interpreted as NULL when storing and retrieving data
//   from the database.
//
// kbmMW_NotNull - Indicate that the property must never contain the NULL value (either interpreted via the kbmMW_Null attribute or actual).
//   Eg.
//   [kbmMW_Field(‘name:somefield‘,ftInteger)]
//   [kbmMW_NotNull]
//   property MyProperty:kbmMWNullable<integer> read FMyProperty write FMyProperty;

时间: 2024-07-30 20:27:21

初始kbmmw 中的ORM的相关文章

KBMMW 中 IOS IPv6 的解决

自从今年苹果强制新上架的APP 必须支持Ipv6,很多原来需要网络支持的APP 就没法上架了. 别的我们就不说了,先说说kbmmw 中,如何解决这个问题. 要测试你的app 是否支持ipv6, 首先要搭建IPv6 的测试环境,最简单的方法就是利用mac 来生成一个 共享的虚拟Ipv6 网络.具体搭建的方法参考此篇博文: http://www.cocoachina.com/ios/20160525/16431.html 剩下的就是在你的APP 里面,是否可以通过这个网络访问远程服务器?如果没问题,

在指定时间干,必须干(kbmmw 中的事件调度)

从去年开始,kbmmw 慢慢增加内涵,除了完善各种服务外,陆续增加和扩展了作为一个中间件必须有的功能, 例如,权限管理.日志系统.调度系统.内存调试等功能. 今天给大家介绍一下kbmmw 的调度事件,调度事件的主要目标就是”在指定时间干,必须干“,不是“爱干”,是“必须干” :). 在传统的delphi 中事件调度室通过两种方式,一种方式通过Ttimer 来实现,(我20年做的母校的食堂餐饮消费系统就是通过Ttimer来轮询 POS 机的).另外一种就是通过扩展Tthread 线程类,通过后台完

kbmmw 中XML 操作入门(跨平台,而且可以与JSON,YAML,BSON 直接互相转换)

delphi 很早以前就自带了xml 的操作,最新版里面有三种XML 解释器,一种是MSXML,看名字就知道 这个是微软自带的,这个据delphi 官方称是速度是最快的,但是只能在windows 上使用.另外两个是 OmniXML, ADOM, 这两个都是跨平台的.但是速度比MSXML 慢点.在delphi 10.2 里面,WINDOWS 应用默认使用MSXML, linux 应用默认使用OmniXML. 当然也可以通过强行改变 今天我们讲一下如何使用kbmmw 内置的XML 解释器处理XML

kbmmw 中虚拟文件操作入门

kbmmw 中一直有一个功能,但是基本上都没有提过,但是在实际应用中,却非常有用,这个功能就是 虚拟文件包功能,他可以把一大堆文件保存到一个文件里面,方便后台管理. kbmmw 的虚拟文件在单元kbmMWStreamStore 中实现,这个是非控件形式的,因此需要手工添加这个 单元.另外虚拟文件操作的类为TkbmMWLookupStorage,所有的操作都有这个类实现,具体可以参加源码. 因为这个很简单,直接就上界面 具体实现代码如下 procedure TForm2.Button1Click(

kbmmw 中JSON 操作入门

现在各种系统中JSON 用的越来越多.delphi 也自身支持JSON 处理. 今天简要说一下kbmmw 内部如何使用和操作JSON. kbmmw 中json的操作是以TkbmMWJSONStreamer 为基础,要导入.导出JSON字符串, 首先要创建TkbmMWJSONStreamer. 然后是 TkbmMWJSONObject和 TkbmMWJSONArray. 先举一个最简单的例子. procedure TForm1.Button3Click(Sender: TObject); var

珍惜每一滴水(kbmmw 中的内存调试)

作为一个服务器端的应用,最基本的要求就是稳定,当然要做一个稳定的服务器端,需要涉及到很多方面, 内存泄露就是稳定的一个致命杀手,因为服务器的物理内存是有限的,即使一个功能有很小的内存泄露,经过 长时间的运行,也会累积成一个非常大的内存泄露,导致服务器内存耗尽,系统崩溃.因此珍惜服务器资源是 开发者必须重视的(当然了,对于内存无法管理的语言及框架,那就算了). 最新版的kbmmw 中加入了内存调试功能,这个功能不但可以应用在kbmmw 服务器中,你也可以在其他程序中 使用. 其实自从delphi

Django中的ORM进阶操作

Django中的ORM进阶操作 Django中是通过ORM来操作数据库的,通过ORM可以很easy的实现与数据库的交互.但是仍然有几种操作是非常绕也特别容易混淆的.于是,针对这一块,来一个分类总结吧. 对于ORM对数据库的基本操作前面model里已经有了介绍,这里专门针对ORM的一对多.多对多.正向.反向等操作来讲解用法和注意事项. 铭记于心的两条: 在联表操作过滤查找数据时用双下划线 "__" 在取数据时用点 "." 一.一对多 首先来设计两张简单的表格,并在其中

kbmmw 中的进程管理小工具

kbmmw 5.6.20 发布了,本版本带来一个小功能,就是可以在kbmmw 应用里面建立和管理进程, 虽然你可以直接调用windows api 做类似的事情,但是kbmmw 里面简化了操作,也加强了管理. 下面简单的说一下这个功能. 首先建立一个新应用,加入单元 kbmMWProcess. 然后我们放置几个控件. 代码很简单.就一句话 procedure TForm1.Button1Click(Sender: TObject); begin TkbmMWProcess.CreateProces

flask 中的ORM

1 响应(response) 1 什么是响应 响应就是由服务器端带给客户端的内容,对应着请求,响应可以是普通的字符串,模板 或重定向 return '普通字符串' return render_template('xxx.html') 2 响应对象 响应对象:将响应的内容封装到一个对象中,可以完成更多的响应的行为(如:增加cookies,..) 在Flask中,使用 make_response() 构建响应对象 2 文件上传 1 注意问题 表单中如果有文件上传的话,必须遵循以下两个要求 1 提交方