EOS 数据库开发实战
上次的文章详细讲解了 EOS 数据库的架构,本文将以官方示例为基础,详解 EOS 数据库的开发实战。git
在智能合约里与 EOS 数据库交互,首先要定义存储的数据:github
const
类型的成员函数primary_key()
,返回值必须为uint64_t
类型,返回值即为主键。存储数据定义好以后,就能够与数据库交互了:数据库
multi_index
,创建数据表。emplace
方法在表中添加数据;使用erace
方法删除数据。modify
方法修改数据。get
、find
方法和其余迭代器操做查询数据。咱们参考 EOS 的官方示例,创建一个“汽车修理店”智能合约所须要的数据库。数据库服务的对象是维修技师和车主。每次车辆维修保养后,维修技师均可以添加本次维修服务的信息,能够更科学地管理每位客户的车辆维修保养服务。并且维修技师和车主均可以更新车辆目前的里程,以便技师肯定车辆是否应该保养。咱们须要一个数据表:维修数据表(service
Table)。segmentfault
维修数据表中,每一条数据对象就是一次车辆维修保养的数据,包含如下成员:架构
咱们还想方便的查询每一个顾客的维修记录,因此须要一个以顾客帐户名为键(Key)的索引。dom
这样咱们就获得了 service_rec
结构体:函数
struct service_rec { uint64_t pkey; // 主键 account_name customer; // 顾客帐户 uint32_t service_date; // 维修日期 uint32_t odometer; // 车辆里程 //设置主键 auto primary_key()const { return pkey; } //设置索引 account_name get_customer()const { return customer; } //SERIALIZE 宏能够帮助提升编译速度 EOSLIB_SERIALIZE( service_rec, (pkey)(customer)(service_date)(odometer) ) };
下面就能够创建数据表了,首先,multi_index
是个模板类:(对 C++ 模板不熟悉的能够百度一下)区块链
eosio::multi_index <uint64_t TableName, typename T, typename... Indices>
咱们须要填入如下multi_index
的模板参数:ui
TableName
为数据表名称,12字符之内,只能使用小写字母,数字1-5,小数点“.”。T
为数据对象类型,这里就是咱们定义的service_rec
结构体。Indices
为索引列表,最多十六个。为了下降开发难度,官方推荐使用const_mem_fun
模板,你们能够模仿官方的作法:按照需求,咱们这样设置multi_index
的模板参数:spa
using service_table_type = multi_index<service/*<-数据表名称*/, service_rec,/*<-数据对象类型*/ /*设置索引->*/indexed_by< N(bycustomer), const_mem_fun<service_rec, account_name, &service_rec::get_customer> > >;
这里并无实例化multi_index
,只是将填入相应模板参数的multi_index
设置了一个别名:service_table_type
。依然,对这里的作法不熟悉的能够看一下 C++ 模板类以及 C++ 的 using 关键字。
下面咱们实例化multi_index
,构造函数须要两个参数:
multi_index( uint64_t code, uint64_t scope )
其中,code
为数据表的拥有者,scope
为数据表的细分名称。这里有两种理解,一种理解是不一样的 scope
就是不一样的数据表,也就是说,在同一个帐户下,存在着TableName
相同的多个数据表,他们的scope
互不相同;另外一种理解:scope
表示了同一个数据表的不一样部分,互相独立读写。这两种理解的结果是同样的,就是惟一肯定一个数据表须要三个参数:TableName
,code
,scope
。
实例化multi_index
:
service_table_type service_table( current_receiver(), mechanic );
上面的code
= current_receiver()
,表示当前的智能合约,即“汽车维修店合约”。若是这里的code
为其余合约,那么说明这个multi_index
指向了其余帐户名下的数据表,在本合约中就只能进行读取操做了。scope
= mechanic
代表实例化的这个multi_index
指向了细分名称为mechanic
(以维修技师帐户命名)的数据表。
咱们所创建的数据表结构以下图所示。
通常数据库的基本操做是增、删、改、查,EOS 数据库固然也具备这些功能。
新增数据须要用到multi_index
的emplace
方法:
const_iterator emplace( unit64_t payer, Lambda&& constructor )
其中的payer
参数位储存空间支付帐户,也就是由谁来提供新加入的这个数据对象的存储空间,这里填入维修技师mechanic
帐户。constructor
是个 Lambda 表达式,也叫匿名函数,是向emplace
方法传入了一个构造函数,用来构造这个新的数据对象。
service_table.emplace(mechanic,/*<-储存空间支付帐户*/ [&]( auto& s_rec )/*<-匿名函数*/ { s_rec.pkey = service_table.available_primary_key(); /*<-系统生成可用主键*/ //匿名函数体 s_rec.customer = eosio::chain::string_to_name(customer_name); //匿名函数体 s_rec.service_date = service_date; //匿名函数体 s_rec.odometer = odometer; //匿名函数体 });
其中的customer_name
、service_date
、odometer
要在实际开发时使用有意义的变量。
因为service_table
数据表的主键是没有意义的,因此咱们须要使用bycustomer
索引来根据顾客帐户名(customer
)查询数据。
auto customer_index = service_table.template get_index<N(bycustomer)>();
这样咱们就获得了bycustomer
索引,咱们可使用索引的find
方法来按照索引查找特定customer
的数据对象。
//创建要查找的帐户,注意这里的customer_name要使用有意义的字符串 account_name customer_acct = eosio::chain::string_to_name(customer_name); //使用`find`方法查找数据,使cust_itr(迭代器)指向所需数据 auto cust_itr = customer_index.find(customer_acct);
若是没有查找到,cust_itr
(迭代器)就是service_table.end()
,也就是搜索到最后也没有找到对应的数据。若是查找成功,cust_itr
(迭代器)就会指向所需的数据对象。
以后,可使用下面的代码能够遍历数据表中全部咱们所需的条目。(由于顾客帐户名不是惟一的,用find
方法会找到符合条件的第一条数据)
while (cust_itr != service_table.end() /*<-判断迭代器位置*/&& cust_itr->customer == customer_acct/*<-判断数据是否符合*/) { // 业务逻辑,对数据进行处理 cust_itr++;//迭代器自增,指向下一条数据 }
在迭代器指向数据后,能够对数据进行修改,使用modify
方法:
service_table.modify(cust_itr,/*<-迭代器*/, mechanic, /*<-储存空间支付帐户*/ [&]( auto& s_rec )/*<-匿名函数*/ { s_rec.customer = new_customer; //匿名函数体 s_rec.service_date = new_service_date; //匿名函数体 s_rec.odometer = new_odometer; //匿名函数体 });
匿名函数中的new_customer
、new_service_date
、new_odometer
请使用有意义的变量。也能够只修改其中部分变量。
在迭代器指向数据后,能够对数据进行删除,使用erase
方法:
service_table.erase( cust_itr/*<-迭代器*/ );
至此,带领你们了初步解了 EOS 数据库开发的思路与方法,EOS 数据库还有不少 API 能够供智能合约使用,你们能够查阅官方 Wiki:
https://github.com/EOSIO/eos/...
圆方圆学院聚集大批区块链名师,打造精品的区块链技术课程。 在各大平台都长期有优质免费公开课,欢迎报名收看。
公开课地址:https://ke.qq.com/course/345101