整了段代码,想用mnesia数据库来实现类似于Oracle中sequence 的功能。
原代码如下:
%% Author: Administrator
%% Created: 2012-2-16
%% Description: TODO: Add description to id_generator
-module(id_generator).
-behavior(gen_server).
%%
%% Include files
%%
%%
%% Exported Functions
%%
-export([start_link/0,getnewid/1]).
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).
-record(ids,{idtype,ids}).
-record(state,{}).
%%
%% API Functions
%%
start_link()->
gen_server:start_link({local,?MODULE}, ?MODULE, [],[])
.
init([])->
mnesia:start(),
io:format("Started"),
mnesia:create_schema([node()]),
case mnesia:create_table(ids,[{type,ordered_set},
{attributes,record_info(fields,ids)},
{disc_copies,[]}
]) of
{atomic,ok}->
{atomic,ok};
{error,Reason}->
io:format("create table error")
end,
{ok,#state{}}
.
getnewid(IdType)->
io:format("waiting ~n"),
%case mnesia:wait_for_tables([tbl_clientid], 5000) of
% ok->
% gen_server:call(?MODULE, {getid,IdType});
% {timeout,_BadList}->
% {timeout,_BadList};
% {error,Reason}->
% {error,Reason}
%end
mnesia:force_load_table(ids),
gen_server:call(?MODULE, {getid,IdType})
.
%%generate new Id with given type
handle_call({getid,IdType},From,State)->
F=fun()->
Result=mnesia:read(ids,IdType,write),
case Result of
[S]->
io:format("have ~n"),
Id=S#ids.ids,
NewClumn=S#ids{ids=Id+1},
mnesia:write(ids,NewClumn,write),
Id;
[]->
io:format("none ~n"),
NewClumn=#ids{idtype=IdType,ids=2},
mnesia:write(ids,NewClumn,write),
1
end
end,
case mnesia:transaction(F)of
{atomic,Id}->
{atomic,Id};
{aborted,Reason}->
io:format("run transaction error ~1000.p ~n",[Reason]),
Id=0;
_Els->
Id=1000
end,
{reply,Id,State}
.
handle_cast(_From,State)->
ok.
handle_info(_From,State)->
ok.
terminate(_From,State)->
ok.
code_change(_OldVer,State,Ext)->
{ok,State}.
%%
%% Local Functions
%%
使用方法:
id_generator:start_link().
id_generator:getnewid(aaa).
总结:
1.要注意将mnsia创建表时的参数写对
2.直接将表的列定义为一个record ,并且第二个字段与表同名
3.表未创建成功,或者有问题时mnesia:wait_for_tables 会超时,最好不要用mnesia:wait_for_tables([mytable],infinity),一旦出错快速结束很重要
4.针对可能异常的地方多判断,做好异常处理