java - 如何使用 hibernate 4 实现自定义线程安全序列?

标签 java multithreading hibernate spring-transactions transaction-isolation

我需要实现一个解决方案来为不同种类但相同类型(相同类,相同表)的对象生成序列号。更重要的是,序列生成的规则是在运行时定义的(起始序列、最大数量等)。 我正在使用 MySQL,hibernate 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。

我怀疑我在这里遗漏了一些非常基本的东西,但无法找到它需要什么才能按预期工作。

感谢任何提示!

最佳答案

使用 select ... for update,Hibernate 支持它 - 请参阅我的 answer here .

关于java - 如何使用 hibernate 4 实现自定义线程安全序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24573027/

相关文章:

java - 如何确认文件是XML格式?

java - 在 Java StAX 解析器中编码

java - 树莓派上的 Tomcat 无法初始化 gnu.io.CommPortIdentifier

c++ - 如何回收 RPC 运行时分配的线程句柄?

java - Sonarqube 不接受我的测试,但它在我的 Eclipse 中工作

hibernate - 如何使用 jboss-log4j.xml 文件将 Hibernate 记录器语句定向到不同应用程序的不同日志文件中

java - 从不同的文件系统加载类文件

iphone - 使用performSelectorInBackground运行加载指示器

java - Jadira 依赖导致 AbstractMethodError

hibernate - 实体管理器 Find() 方法的正确使用