高低位算法是Hibernate的一种主键生成策略,使用一个高位值和一个低位值,然后把算法得到的两个值拼接起来作为数据库中的唯一主键。
Hilo算法需要额外的数据库表的支持,但不需要每次生成都去查询数据库,查询数据库的频率取决于maxLo。
创建数据库表
CREATE TABLE `sn` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`lastValue` bigint(20) NOT NULL,
`name` varchar(32) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`)
)
高低位算法Java代码
/**
* 高低位算法生成器
*/
private class HiloOptimizer {
/**
* 根据name查询对应lastValue
*/
private String name;
/**
* 前缀,例如日期
*/
private String prefix;
/**
* 最大低位值,决定查询数据库的频率
*/
private int maxLo;
/**
* 低位值
*/
private int lo;
/**
* 高位值
*/
private long hi;
/**
* 末值
*/
private long lastValue;
/**
* 构造方法
*/
HiloOptimizer(String name, String prefix, int maxLo) {
this.name = name;
this.prefix = prefix;
this.maxLo = maxLo;
//初始化时使 lo > maxLo
this.lo = maxLo + 1;
}
/**
* 生成编号
*/
public synchronized String generate() {
if (lo > maxLo) {
//调用查询方法获得末值,使其自增并更新到数据库中
lastValue = getLastValue(name);
//改变lo的值
lo = 0;
//高位值进位
hi = lastValue * (maxLo + 1);
}
//拼接编号,lo+1
return prefix + (hi + lo++);
}
}
/**
* 获取末值
*/
private long getLastValue(String name) {
String jpql = "select sn from Sn sn where sn.name like :name";
Sn sn = entityManager.createQuery(jpql, Sn.class).setLockMode(LockModeType.PESSIMISTIC_WRITE).setParameter("name", name).getSingleResult();
long lastValue = sn.getLastValue();
sn.setLastValue(lastValue + 1);
return lastValue;
}