我目前在Spring Hibernate中遇到种族问题(通过在service和daoImpl类上的注释进行事务处理)。这是我所遇到的:
表格:
注意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可以将其拾取并知道当第二个线程再次尝试插入时,则不需要这样做。但是,尽管我尝试了各种传播和隔离模式,但都没有发生。我必须缺少一些非常基础的东西,请向我指出如何解决此问题的正确方向。提前感谢您的回复。如果需要/要求,我将提供更多信息。
这是设计使然。默认情况下,您仅会看到已提交的行(READ COMMITTED隔离级别)。对于外部进程,可以将未提交的行视为数据库中尚不存在。
最佳解决方案是捕获唯一的约束违例并重试(最好是延迟)。您还可以将隔离级别设置为“未提交”,但这可能会导致其他竞争条件,因此我不建议这样做。