基本思路:
* 数据库表通过Hibernate映射为实体类,主键通过序列号生成器(KeyGenerator)生成;
* 序列号生成器以Singleton方式工作,并维护所有需要维护的实体的序列号(KeyBean);
* 列号生成器缓存一定的键值,避免每次取序列号都从数据库获取;
* 数据库建立实体和当前键值对应表,每从列号生成器获取一个序列时,同步到该键值对应表,避免宕机后不一致
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
1
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_0
141
*
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
}
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_022
*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
@Override49
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 clazz66
* @return67
*/68

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

72

/** *//**73
* 生成序列号,并同步至数据库74
* 此方法可以根据自己需要定义生成序列号的规则75
* @param clazz76
* @return77
*/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 classPath95
*/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
}
本文介绍了一种基于单例模式的序列号生成器实现方案,该方案利用Hibernate将数据库表映射为实体类,通过维护实体的序列号并进行缓存来提高效率,同时确保了系统的稳定性和一致性。
&spm=1001.2101.3001.5002&articleId=82175011&d=1&t=3&u=8d743f9f61ce446e927acbea6998ce1c)
778

被折叠的 条评论
为什么被折叠?



