朋友! 我正在使用Play + Java + Ebean。 尝试以一种方法选择值并将其插入数据库时,并行线程出现问题。 首先,我通过id检查DB(PostgreSQL)中是否存在设备。 如果没有按ID查找设备,则尝试将其插入数据库。 然后我返回设备对象。 除了两个http请求异步尝试向我发送相同的设备ID的情况以外,其他所有方法都工作正常。首先,他们两个都从DB中选择一个值,并且什么也不返回。然后一个插入值,第二个由于io.eBean.DuplicateKeyException而失败。
我尝试同步方法。它可行,但我不喜欢这种解决方案。如果我这样做,许多请求将被排入队列。我想保持并行,但仅在我有两个或多个具有相同ID的请求时才进行同步。 解决该问题的另一种方法是使用INSERT ... WHERE NOT EXISTS(SELECT ...)RETURNING编写查询。但这不是对象样式,并且对相同类型的多个操作进行了硬编码。
public CompletionStage<Device> getDevice(String deviceID, String ipAddress) {
return CompletableFuture.supplyAsync(() ->
SecurityRepository.findDeviceByDeviceID(deviceID))
.thenApplyAsync(curDevice -> curDevice
.orElseGet(() -> {
List<Device> devices =
SecurityRepository.listDevicesByIpAddress(ipAddress);
if(devices.size() >= 10) {
for(Device device : devices)
device.delete();
}
Device newDevice = new Device();
newDevice.setDeviceID(deviceID);
newDevice.ipAddress = ipAddress;
newDevice.save(); //here is the problem
return newDevice;
})
);
}
仅当deviceID相同时,我才想同步此方法。 您对这个问题有什么建议吗? 谢谢。