У меня есть вопрос для меня. Я создал синхронизированный Service
, который вызывается Controller
:
@Controller
public class WebAppApiController {
private final WebAppService webApService;
@Autowired
WebAppApiController(WebAppService webApService){
this.webApService= webApService;
}
@Transactional
@PreAuthorize("hasAuthority('ROLE_API')")
@PostMapping(value = "/api/webapp/{projectId}")
public ResponseEntity<Status> getWebApp(@PathVariable(value = "projectId") Long id, @RequestBody WebAppRequestModel req) {
return webApService.processWebAppRequest(id, req);
}
}
Service
Слой просто проверяет, нет ли дубликата в запросе, и сохраняет его в базе данных. Поскольку клиент, использующий эту конечную точку, постоянно выполняет МНОЖЕЕ запросов, случилось так, что до того, как один запрос был проверен, дубликат другого был помещен в базу данных, поэтому я пытаюсь выполнить синхронизированный блок.
@Service
public class WebAppService {
private final static String UUID_PATTERN_TO = "[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}";
private final WebAppRepository waRepository;
@Autowired
public WebAppService(WebAppRepository waRepository){
this.waRepository= waRepository;
}
@Transactional(rollbackOn = Exception.class)
public ResponseEntity<Status> processScanWebAppRequest(Long id, WebAppScanModel webAppScanModel){
try{
synchronized (this){
Optional<WebApp> webApp=verifyForDuplicates(webAppScanModel);
if(!webApp.isPresent()){
WebApp webApp=new WebApp(webAppScanModel.getUrl())
webApp=waRepository.save(webApp);
processpropertiesOfWebApp(webApp);
return new ResonseEntity<>(HttpStatus.CREATED);
}
return new ResonseEntity<>(HttpStatus.CONFLICT);
}
} catch (NonUniqueResultException ex){
return new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
} catch (IncorrectResultSizeDataAccessException ex){
return new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
}
}
}
Optional<WebApp> verifyForDuplicates(WebAppScanModel webAppScanModel){
return waRepository.getWebAppByRegex(webAppScanModel.getUrl().replaceAll(UUID_PATTERN_TO,UUID_PATTERN_TO)+"$");
}
И метод JPA:
@Query(value="select * from webapp wa where wa.url ~ :url", nativeQuery = true)
Optional<WebApp> getWebAppByRegex(@Param("url") String url);
processpropertiesOfWebApp
метод выполняет дальнейшую обработку для данного веб-приложения, которое на данный момент должно быть уникальным.
Предполагаемое поведение: когда клиентский запрос на публикацию содержит несколько URL, например:
https://testdomain.com/user/7e1c44e4-821b-4d05-bdc3-ebd43dfeae5f
https://testdomain.com/user/d398316e-fd60-45a3-b036-6d55049b44d8
https://testdomain.com/user/c604b551-101f-44c4-9eeb-d9adca2b2fe9
Только первая будет сохранена в базе данных, но в данный момент это не то, что происходит. Выберите из моей базы данных:
select inserted,url from webapp where url ~ 'https://testdomain.com/users/[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}$';
2019-11-07 08:53:05 | https://testdomain.com/users/d398316e-fd60-45a3-b036-6d55049b44d8
2019-11-07 08:53:05 | https://testdomain.com/users/d398316e-fd60-45a3-b036-6d55049b44d8
2019-11-07 08:53:05 | https://testdomain.com/users/d398316e-fd60-45a3-b036-6d55049b44d8
(3 rows)
Я попытаюсь добавить ограничение unique
к столбцу url
, но я не могу себе представить, что это решит проблему, в то время как когда UUID
изменит новый url
, будетбыть unique
Может ли кто-нибудь подсказать мне, что я делаю неправильно?
Вопрос связан с вопросом, который я спрашивал раньше , но не нашел правильного решения, поэтомуЯ упростила свой метод, но все еще безуспешно