EOS 数据库与持久化 API —— 实战
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EOS 数据库与持久化 API —— 实战相关的知识,希望对你有一定的参考价值。
EOS 数据库开发实战
上次的文章详细讲解了 EOS 数据库的架构,本文将以官方示例为基础,详解 EOS 数据库的开发实战。
基本步骤
在智能合约里与 EOS 数据库交互,首先要定义存储的数据:
定义对象:具体就是定义一个 C++ 类或者 C++ 结构体,数据表就由一个个对象组成。
定义主键:在刚才的类/结构体中,定义一个
const
类型的成员函数primary_key()
,返回值必须为uint64_t
类型,返回值即为主键。定义索引:EOS 数据表不光可以按照主键搜索数据,还可以定义多达 16 种索引。而且索引键(Key)不止支持64位无符号整数,还支持 128、256位整数以及双精度、四精度浮点数。
为每个索引定义键提取器(key extractor)。
存储数据定义好之后,就可以与数据库交互了:
建立数据表:实例化 multi_index,建立数据表。
增删数据:使用
emplace
方法在表中添加数据;使用erace
方法删除数据。修改数据:使用
modify
方法修改数据。查询数据:使用
get
、find
方法和其他迭代器操作查询数据。
需求分析
我们参考 EOS 的官方示例,建立一个“汽车修理店”智能合约所需要的数据库。数据库服务的对象是维修技师和车主。每次车辆维修保养后,维修技师都可以添加本次维修服务的信息,可以更科学地管理每位客户的车辆维修保养服务。而且维修技师和车主都可以更新车辆目前的里程,以便技师确定车辆是否应该保养。我们需要一个数据表:维修数据表(service
Table)。
建立数据对象
维修数据表中,每一条数据对象就是一次车辆维修保养的数据,包含以下成员:
主键:因为数据表主键必须是唯一的,所以无法用顾客的账户名作为主键(同一个顾客有多条维修记录)。这里我们让系统自动生成主键。
顾客账户:存储每次维修服务的顾客账户名。
维修日期:每次维修服务的日期。
车辆里程:每次服务时,车辆的里程信息。
我们还想方便的查询每个顾客的维修记录,所以需要一个以顾客账户名为键(Key)的索引。
这样我们就得到了 service_rec
结构体:
建立数据表
下面就可以建立数据表了,首先,multi_index
是个模板类:(对 C++ 模板不熟悉的可以百度一下)
我们需要填入以下multi_index
的模板参数:
TableName
为数据表名称,12字符以内,只能使用小写字母,数字1-5,小数点“.”。T
为数据对象类型,这里就是我们定义的service_rec
结构体。Indices
为索引列表,最多十六个。为了降低开发难度,官方推荐使用const_mem_fun
模板,大家可以模仿官方的做法:
按照需求,我们这样设置multi_index
的模板参数:
这里并没有实例化multi_index
,只是将填入相应模板参数的multi_index
设置了一个别名:service_table_type
。依然,对这里的做法不熟悉的可以看一下 C++ 模板类以及 C++ 的 using 关键字。
下面我们实例化multi_index
,构造函数需要两个参数:
其中,code
为数据表的拥有者,scope
为数据表的细分名称。这里有两种理解,一种理解是不同的 scope
就是不同的数据表,也就是说,在同一个账户下,存在着TableName
相同的多个数据表,他们的scope
互不相同;另一种理解:scope
表示了同一个数据表的不同部分,互相独立读写。这两种理解的结果是一样的,就是唯一确定一个数据表需要三个参数:TableName
,code
,scope
。
实例化multi_index
:
上面的code
= current_receiver()
,表示当前的智能合约,即“汽车维修店合约”。如果这里的code
为其他合约,那么说明这个multi_index
指向了其他账户名下的数据表,在本合约中就只能进行读取操作了。scope
= mechanic
表明实例化的这个multi_index
指向了细分名称为mechanic
(以维修技师账户命名)的数据表。
我们所建立的数据表结构如下图所示。
操作数据
一般数据库的基本操作是增、删、改、查,EOS 数据库当然也具有这些功能。
新增数据
新增数据需要用到multi_index
的emplace
方法:
其中的payer
参数位储存空间支付账户,也就是由谁来提供新加入的这个数据对象的存储空间,这里填入维修技师mechanic
账户。constructor
是个 Lambda 表达式,也叫匿名函数,是向emplace
方法传入了一个构造函数,用来构造这个新的数据对象。
其中的customer_name
、service_date
、odometer
要在实际开发时使用有意义的变量。
查询数据
由于service_table
数据表的主键是没有意义的,所以我们需要使用bycustomer
索引来根据顾客账户名(customer
)查询数据。
这样我们就得到了bycustomer
索引,我们可以使用索引的find
方法来按照索引查找特定customer
的数据对象。
如果没有查找到,cust_itr
(迭代器)就是service_table.end()
,也就是搜索到最后也没有找到对应的数据。如果查找成功,cust_itr
(迭代器)就会指向所需的数据对象。
之后,可以使用下面的代码可以遍历数据表中所有我们所需的条目。(因为顾客账户名不是唯一的,用find
方法会找到符合条件的第一条数据)
修改数据
在迭代器指向数据后,可以对数据进行修改,使用modify
方法:
匿名函数中的new_customer
、new_service_date
、new_odometer
请使用有意义的变量。也可以只修改其中部分变量。
删除数据
在迭代器指向数据后,可以对数据进行删除,使用erase
方法:
至此,带领大家了初步解了 EOS 数据库开发的思路与方法,EOS 数据库还有很多 API 可以供智能合约使用,大家可以查阅官方 Wiki:
https://github.com/EOSIO/eos/wiki/Persistence-API
以上是关于EOS 数据库与持久化 API —— 实战的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot企业级开发前后端分离博客系统+Thymeleaf实战+Jpa数据持久化实战+全文检索实战+架构设计与分层+API设计
Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段
SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介创建消息生产者创建消息消费者自定义消息通道分组与持久化设置 RoutingKey)(代码片段