之前在BlogJava上发表过这篇文章,那时没怎么做整理。想不到已经有博友把它弄到ITEye来了(虽然写得水平差,但还是希望那位博友能注明是转载的)。这次稍作了整理,自己也加深下印象。
使用场景:用于生成实体主键键值,每次增长1。
框架支持:spring,hibernate
工作方式:单例,序列号生成器支持缓存键值,可设定每次取键的个数。用于集群环境时,取键个数设为1即可。
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.pro.base.model.TableKey;
import com.pro.base.service.BasicService;
/***
* 基于单例模式的多键值带缓存序列号生成器
*
* 思路:
* 数据库表通过Hibernate映射为实体类,主键通过序列号生成器(KeyGenerator)生成;
* 序列号生成器以Singleton方式工作,并维护所有需要维护的实体的序列号(KeyBean);
* 列号生成器缓存一定的键值,避免每次取序列号都从数据库获取;
* 数据库建立实体和当前键值对应表,每从列号生成器获取一个序列时,同步到该键值对应表,避免宕机后不一致
*
* @author o_oand0_0
*
*/
public class KeyGenerator implements ApplicationContextAware {
//实现ApplicationContextAware,Spring对applicationContext自动装配
private ApplicationContext applicationContext;
//键值实体类
private Map<String, KeyBean> keyMap;
//数据库服务
private BasicService basicService;
//设置要缓存的键值的数量,建议在团队开发测试时设为1,省得总出现主键冲突,到上线后再调大
//另外集群环境下使用时,需要把该值设为1,相当于每次取键值的时候同时更新数据库
private static long keyNum=20;
private static final KeyGenerator instance=null;
private KeyGenerator() {
basicService=(BasicService)applicationContext.getBean("basicService");
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext=applicationContext;
}
//以单例方式获取序列号生成器
public static synchronized KeyGenerator getInstance(){
if(instance==null){
return new KeyGenerator();
}else{
return instance;
}
}
/**
* 根据类名获取序列号
* @param clazz
* @return
*/
public String generatorKey(Class clazz){
return getKey(clazz);
}
/**
* 生成序列号,并同步至数据库
* 此方法可以根据自己需要定义生成序列号的规则
* @param clazz
* @return
*/
public String getKey(Class clazz) {
if (keyMap == null) {
keyMap = new ConcurrentHashMap<String, KeyBean>();
}
KeyBean kb = keyMap.get(clazz.getName());
if (kb == null||kb.getMaxIndex()==kb.getNowIndex()) {
updateKeyBean(clazz.getName());
}
kb = keyMap.get(clazz.getName());
long now=kb.getNowIndex();
kb.setNowIndex(now+1);
return now+"";
}
/**
* 同步序列值到数据库,并修改序列号生成器对应实体的下一键值
* @param classPath
*/
private void updateKeyBean(String classPath) {
TableKey tk = (TableKey) basicService.expandObjectByKey(TableKey.class.getName(),
classPath);
KeyBean kb=new KeyBean();
kb.setKeyName(classPath);
try {
if (tk == null) {
tk=new TableKey();
kb.setMaxIndex(keyNum);
kb.setNowIndex(1);
tk.setTableName(classPath);
tk.setNowIndex(""+keyNum);
basicService.insert(tk);
} else {
kb.setMaxIndex(keyNum+Long.valueOf(tk.getNowIndex()));
kb.setNowIndex(Long.valueOf(tk.getNowIndex()));
tk.setNowIndex(Long.valueOf(tk.getNowIndex()) + keyNum + "");
basicService.update(tk);
}
keyMap.put(classPath, kb);
} catch (Exception e) {
e.printStackTrace();
}
}
public Map<String, KeyBean> getKeyMap() {
return keyMap;
}
public void setKeyMap(Map<String, KeyBean> keyMap) {
this.keyMap = keyMap;
}
public BasicService getBasicService() {
return basicService;
}
public void setBasicService(BasicService basicService) {
this.basicService = basicService;
}
/***
* 键值实体类
* @author o_oand0_0
*
*/
protected class KeyBean {
private String keyName;
private long nowIndex;
private long maxIndex;
public String getKeyName() {
return keyName;
}
public void setKeyName(String keyName) {
this.keyName = keyName;
}
public long getNowIndex() {
return nowIndex;
}
public void setNowIndex(long nowIndex) {
this.nowIndex = nowIndex;
}
public long getMaxIndex() {
return maxIndex;
}
public void setMaxIndex(long maxIndex) {
this.maxIndex = maxIndex;
}
}
}
/**
* TableKey 实体.
* 记录实体的类名和当前的索引号,对应数据库表table_key
* @author o_oand0_0
*/
public class TableKey implements java.io.Serializable {
// Fields
private String tableName;
private String nowIndex;
// Constructors
/** default constructor */
public TableKey() {
}
/** full constructor */
public TableKey(String tableName, String nowIndex) {
this.tableName = tableName;
this.nowIndex = nowIndex;
}
// Property accessors
public String getTableName() {
return this.tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getNowIndex() {
return this.nowIndex;
}
public void setNowIndex(String nowIndex) {
this.nowIndex = nowIndex;
}
}
需要在applicationContext.xml中生成器:
<bean name="keyGenerator" class="com.pro.base.util.KeyGenerator">
<property name="basicService" ref="basicService"></property>
</bean>
使用方法:
String keyId = KeyGenerator.getInstance().getKey(Attachments.class);
分享到:
相关推荐
cod4序列号生成器 cod4序列号生成器
卡巴斯基序列号生成器
Steelray Project Viewer序列号生成器noy-steelray.project.viewer.keygen.jar 支持5.0以上版本,其他版本未测试 运行需安装jdk、jre 另,内含多个可用的license
EnterpriseArchitect 8.0.858 序列号生成器
web storm 序列号生成器, 破解, 支持当前最新的WebStorm3.03, 3.03版本支持NodeJS的开发. 非常好用的JavaScript的开发工具.
可以产生VMware各个版本序列号的生成器
adobe-dreamwear cs4序列号生成器
完全意义上的 汉语大辞典5.87序列号生成程序,不是程序的破解,真正的注册序列号,一台机器对应很多序列号,选择一个输入即可完美注册
软件序列号生成器,通取物理地址,实现对MAC地址的绑定。加密好工具。
eset 序列号生成器eset 序列号生成器eset 序列号生成器eset 序列号生成器
vmware workstation 10 序列号生成器,不用科普了。
经过多次尝试和搜索,经本人验证确实可以完美破解Delphi和C++ Builder XE5的破解工具和序列号生成器。
易语言序列号生成器源码,序列号生成器,十六进制到十进制,十进制到十六进制,序列号显示,序列号算法,序列号反算,读取授权文件,秘密,wvsprintfA,StrToIntExA
eclipse序列号生成器,方便大家在使用eclipse的时间生成序列号用。
matlab7的序列号生成器,挺有用的,但matlab7对vista支持不太好
NULL 博文链接:https://hangyu608.iteye.com/blog/990926
VMware是全球云基础架构和移动商务解决方案厂商,提供基于VMware的解决方案,企业通过数据中心改造和公有云整合业务,借助企业安全转型维系客户信任
VMware workstation 7.1.4序列号生成器,自己使用没有问题,特别推荐
系统硬盘序列号 网卡MAC 主板信息 支持Windows10 1809 1903 1909 2004 20h2 21h1 使用方法就是依次输入1 2 3就行 重启不会自动恢复 : 随机化注册表和重置网卡数据 重启会自动恢复 : 加载匿名驱动 建议配合影子系统...
一款很强大的虚拟机序列号生成器 不用费劲在网上找 直接可以生成