2013-04-08 89 views
1

我目前有一个与Spring Hibernate(通过服务和daoImpl类的注释事务)的种族问题。以下是我曾经遇到过:春季冬眠插入竞争条件

表:

  • 设备类型:ID(序列),名
  • 设备:ID(序列),device_identifier,device_type_id,IP_ADDRESS

注device_identifier和device_type_id在一起是唯一的

这是我在多线程过程中的一个片段:

if(deviceDao.findByIdentifierAndTypeId(identifier, typeId) == null){ 
     Device newDevice = new Device(); 
     newDevice.setIdentifier(identifier); 
     newDevice.setTypeId(typeId); 
     deviceDao.add(newDevice); 
    } 

所以会发生什么是,我有透过WebSocket(这里可能不是重要的细节)监听设备的服务器,服务器将首先尝试以确定设备是否已经在数据库和设备记录如果尚未找到,则创建。

现在我遇到的问题是服务器可以处理来自设备的多个消息(线程是从设备的每条消息创建的),因此也是竞争条件。

所以,想象这样的:

设备A发送两个消息一前一后:

Sends hello message    Sends "here is my ip" message 
      |         | 
      |         | 
      |         | 
    does not see device in DB      | 
     tries to insert    does not see device in DB 
      |        tries to insert 
      Insert completed      | 
           Failed to insert (Unique key constraints not met) 

显然,当该设备是被插入在第二时间,唯一约束将导致失败。但我在想,当第一次插入完成时,Spring将能够接受它并知道当第二个线程再次尝试插入时它不需要。但尽管我尝试了各种传播和隔离模式,但这并没有发生。我必须错过一些非常基本的东西,请指出我如何解决这个问题的正确方向。提前感谢您的回复。如果需要/我会提供更多信息。

回答

1

这是设计行为。默认情况下,你只会看到提交的行(READ COMMITTED隔离级别)。对于外部进程,您可以将未提交的行视为还不存在于数据库中。

最好的解决方案是捕获唯一约束违规并重试(理想情况下延迟)。您也可以将隔离级别设置为未提交读取,但这可能会产生其他竞争条件,我不会推荐这样做。

+0

谢谢,这就是我最终做的。起初,它似乎不是一种处理它的优雅方式,但是当我更多地考虑它时,除了重试刷新唯一ID之外,确实没有其他方式。 – 2013-10-09 23:12:57