基本思路:
* 数据库表通过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
}

2

3

4

5

6

7

8

9

10

11

12


13

14

15

16

17

18

19

20

21

22

23

24



25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40



41

42

43

44



45

46

47

48

49

50



51

52

53

54

55



56



57

58



59

60

61

62

63


64

65

66

67

68



69

70

71

72


73

74

75

76

77

78



79



80

81

82

83



84

85

86

87

88

89

90

91

92


93

94

95

96



97

98

99

100

101



102



103

104

105

106

107

108

109



110

111

112

113

114

115

116



117

118

119

120

121



122

123

124

125



126

127

128

129



130

131

132

133

134



135

136

137

138


139

140

141

142

143



144

145

146

147

148



149

150

151

152



153

154

155

156



157

158

159

160



161

162

163

164



165

166

167

168



169

170

171

172

173
