基于单例模式的多键值序列号生成器实现(带缓存)
基本思路:
?* 数据库表通过Hibernate映射为实体类,主键通过序列号生成器(KeyGenerator)生成;
?* 序列号生成器以Singleton方式工作,并维护所有需要维护的实体的序列号(KeyBean);
?* 列号生成器缓存一定的键值,避免每次取序列号都从数据库获取;
?* 数据库建立实体和当前键值对应表,每从列号生成器获取一个序列时,同步到该键值对应表,避免宕机后不一致
package?com.pro.base.util;??2

??3
import?java.util.Map;??4
import?java.util.concurrent.ConcurrentHashMap;??5
import?org.springframework.beans.BeansException;??6
import?org.springframework.context.ApplicationContext;??7
import?org.springframework.context.ApplicationContextAware;??8

??9
import?com.pro.base.model.TableKey;?10
import?com.pro.base.service.BasicService;?11

?12

/**?*//***?13
?*?基于单例模式的多键值带缓存序列号生成器?14
?*??15
?*?思路:?16
?*?数据库表通过Hibernate映射为实体类,主键通过序列号生成器(KeyGenerator)生成;?17
?*?序列号生成器以Singleton方式工作,并维护所有需要维护的实体的序列号(KeyBean);?18
?*?列号生成器缓存一定的键值,避免每次取序列号都从数据库获取;?19
?*?数据库建立实体和当前键值对应表,每从列号生成器获取一个序列时,同步到该键值对应表,避免宕机后不一致?20
?*??21
?*?@author?o_oand0_0?22
?*?23
?*/?24

public?class?KeyGenerator?implements?ApplicationContextAware?
{?25
?????26
????//实现ApplicationContextAware,Spring对applicationContext自动装配;需要把KeyGenerator配置到Spring容器?27
????private??ApplicationContext?applicationContext;?28

?29
????//键值实体类?30
????private?Map<String,?KeyBean>?keyMap;?31
?????32
????//数据库服务?33
????private?BasicService?basicService;?34
?????35
????//设置要缓存的键值的数量,建议在团队开发测试时设为1,省得总出现主键冲突,到上线后再调大?36
????private?static?long?keyNum=20;?37
?????38
????private?static?final?KeyGenerator?instance=null;?39
?????40

????private?KeyGenerator()?
{?41
????????basicService=(BasicService)applicationContext.getBean("basicService");?42
????}?43
?????44

????public??ApplicationContext?getApplicationContext()?
{?45
????????return?applicationContext;?46
????}?47

?48
????@Override?49
????public?void?setApplicationContext(ApplicationContext?applicationContext)?50

????????????throws?BeansException?
{?51
????????this.applicationContext=applicationContext;?52
????}?53
?????54
????//以单例方式获取序列号生成器?55

????public?static?synchronized??KeyGenerator?getInstance()
{?56

????????if(instance==null)
{?57
????????????return?new?KeyGenerator();?58

????????}else
{?59
????????????return?instance;?60
????????}?61
????}?62
?????63

????/**?*//**?64
?????*?根据类名获取序列号?65
?????*?@param?clazz?66
?????*?@return?67
?????*/?68

????public??String?generatorKey(Class?clazz)
{?69
????????return?getKey(clazz);?70
????}?71

?72

????/**?*//**?73
?????*?生成序列号,并同步至数据库?74
?????*?此方法可以根据自己需要定义生成序列号的规则?75
?????*?@param?clazz?76
?????*?@return?77
?????*/?78

????public?String?getKey(Class?clazz)?
{?79

????????if?(keyMap?==?null)?
{?80
????????????keyMap?=?new?ConcurrentHashMap<String,?KeyBean>();?81
????????}?82
????????KeyBean?kb?=?keyMap.get(clazz.getName());?83

????????if?(kb?==?null||kb.getMaxIndex()==kb.getNowIndex())?
{?84
????????????updateKeyBean(clazz.getName());?85
????????}?86
????????kb?=?keyMap.get(clazz.getName());?87
????????long?now=kb.getNowIndex();?88
????????kb.setNowIndex(now+1);?89
????????return?now+"";?90
????}?91

?92

????/**?*//**?93
?????*?同步序列值到数据库,并修改序列号生成器对应实体的下一键值?94
?????*?@param?classPath?95
?????*/?96

????private?void?updateKeyBean(String?classPath)?
{?97
????????TableKey?tk?=?(TableKey)?basicService.expandObjectByKey(TableKey.class.getName(),?98
????????????????classPath);?99
????????KeyBean?kb=new?KeyBean();100
????????kb.setKeyName(classPath);101

????????try?
{102

????????????if?(tk?==?null)?
{103
????????????????tk=new?TableKey();104
????????????????kb.setMaxIndex(keyNum);105
????????????????kb.setNowIndex(1);106
????????????????tk.setTableName(classPath);107
????????????????tk.setNowIndex(""+keyNum);108
????????????????basicService.insert(tk);109

????????????}?else?
{110
????????????????kb.setMaxIndex(keyNum+Long.valueOf(tk.getNowIndex()));111
????????????????kb.setNowIndex(Long.valueOf(tk.getNowIndex()));112
????????????????tk.setNowIndex(Long.valueOf(tk.getNowIndex())?+?keyNum?+?"");113
????????????????basicService.update(tk);114
????????????}115
????????????keyMap.put(classPath,?kb);????????????116

????????}?catch?(Exception?e)?
{117
????????????e.printStackTrace();118
????????}119
????}120

121

????public?Map<String,?KeyBean>?getKeyMap()?
{122
????????return?keyMap;123
????}124

125

????public?void?setKeyMap(Map<String,?KeyBean>?keyMap)?
{126
????????this.keyMap?=?keyMap;127
????}128

129

????public?BasicService?getBasicService()?
{130
????????return?basicService;131
????}132

133
????134

????public?void?setBasicService(BasicService?basicService)?
{135
????????this.basicService?=?basicService;136
????}137
????138

????/**?*//***139
?????*?键值实体类140
?????*?@author?o_oand0_0141
?????*142
?????*/143

????protected?class?KeyBean?
{144
????????private?String?keyName;145
????????private?long?nowIndex;146
????????private?long?maxIndex;147

148

????????public?String?getKeyName()?
{149
????????????return?keyName;150
????????}151

152

????????public?void?setKeyName(String?keyName)?
{153
????????????this.keyName?=?keyName;154
????????}155

156

????????public?long?getNowIndex()?
{157
????????????return?nowIndex;158
????????}159

160

????????public?void?setNowIndex(long?nowIndex)?
{161
????????????this.nowIndex?=?nowIndex;162
????????}163

164

????????public?long?getMaxIndex()?
{165
????????????return?maxIndex;166
????????}167

168

????????public?void?setMaxIndex(long?maxIndex)?
{169
????????????this.maxIndex?=?maxIndex;170
????????}171
????}172
????173
}1 楼 tan4836128 2011-10-25 有什么用?连实现场景都不能介绍,只能走马观花打打酱油,这样的文章也能上ITeye首页,不值一读! 2 楼 sssheep 2011-10-25 集群方式下能保证不产生重复的? 3 楼 o_oand0_0 2011-12-28 sssheep 写道集群方式下能保证不产生重复的?
我来替楼主回答:
集群方式下只要把取键的数量设为1就可以。相当于每次取键都和数据库同步。
另外,请楼主标明为转载。
地址:http://www.blogjava.net/o-oand0-0/archive/2011/10/21/361752.html
本人虽然写得不怎么的,但对于程序员来说,程序就像亲儿子。