【发布时间】:2014-08-25 17:14:06
【问题描述】:
我需要实现一个解决方案来为不同种类但相同类型的对象(相同的类,相同的表)生成序列号。更重要的是,序列生成的规则是在运行时定义的(起始序列、最大数量等)。 我正在使用 MySQL,休眠 MySQL5Dialect 不支持序列生成,因此我选择使用序列表来实现此功能,其中每一行是不同类型对象的序列:
+--------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| seqenceName | varchar(255) | NO | PRI | NULL | |
| nextVal | bigint(20) | NO | | NULL | |
+--------------------+--------------+------+-----+---------+-------+
我创建了一个增加值的 dao:
public synchronized long getNextValue(String seqenceName) throws MySequenceNotFoundException {
MySequence seq = findByID(seqenceName);
if (seq == null) {
throw new MySequenceNotFoundException("Sequence does not exist with name: " + seqenceName);
}//if not exists
long nextVal = seq.getNextVal();
getCurrentSession().saveOrUpdate(seq);
return nextVal;
}
这从服务层调用为:
@Transactional(readOnly=false, propagation=Propagation.REQUIRES_NEW, isolation=Isolation.SERIALIZABLE)
public synchronized long incSequence(String seqName) throws MySequenceNotFoundException {
getCurrentSession().getTransaction().begin();
MySequence seq = sequenceDao.findByID(seqName);
LockRequest lockRequest = getCurrentSession().buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_WRITE));
lockRequest.lock(seq);
long l = sequenceDao.getNextValue(seqName);
getCurrentSession().getTransaction().commit();
return l;
}
我尝试了一切:将隔离级别设置为Isolation.SERIALIZABLE,以编程方式在方法内提交事务,向其中添加synchronized 关键字,还添加了锁定请求,但我认为它已经过时了,因为隔离级别已经设置。
如果我创建 100 个线程并从每个线程调用此方法 60 次,结果是 nextVal 列的值约为 4000 而不是 6000。
我怀疑我在这里遗漏了一些非常基本的东西,但不知道需要什么才能按预期工作。
感谢任何提示!
【问题讨论】:
-
您好,您找到解决问题的方法了吗?我也面临同样的问题。
标签: java multithreading hibernate spring-transactions transaction-isolation