Я провел день за днем, пытаясь найти решение моей проблемы с помощью транзакционных методов. Логика такая:
Контроллер получает запрос, вызывает queueService, помещает его в PriorityBlockingQueue, а другой поток обрабатывает данные (поиск карт, обновление статуса, назначение текущей игре, возврат данных)
Контроллер:
@RequestMapping("/queue")
public DeferredResult<List<Card>> queueRequest(@Params...){
queueService.put(result, size, terminal, time)
result.onCompletion(() -> assignmentService.assignCards(result, game,room, cliente));
}
QueueService:
@Service
public class QueueService {
private BlockingQueue<RequestQueue> queue = new PriorityBlockingQueue<>();
@Autowired
GameRepository gameRepository;
@Autowired
TerminalRepository terminalRepository;
@Autowired
RoomRpository roomRepository;
private long requestId = 0;
public void put(DeferredResult<List<Card>> result, int size, String client, LocalDateTime time_order){
requestId++;
--ommited code(find Entity: game, terminal, room)
try {
RequestQueue request= new RequestCola(requestId, size, terminal,time_order, result);
queue.put(request);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
CardService:
@Transactional
public class CardService {
@Autowired
EntityManager em;
@Autowired
CardRepository cardRepository;
@Autowired
AsignService asignacionService;
public List<Cards> processRequest(int size, BigDecimal value)
{
List<Card> carton_query = em.createNativeQuery("{call cards_available(?,?,?)}",
Card.class)
.setParameter(1, false)
.setParameter(2, value)
.setParameter(3, size).getResultList();
List<String> ids = new ArrayList<String>();
carton_query.forEach(action -> ids.add(action.getId_card()));
String update_query = "UPDATE card SET available=true WHERE id_card IN :ids";
em.createNativeQuery(update_query).setParameter("ids", ids).executeUpdate();
return card_query;
}
QueueExecutor (Consumer)
@Component
public class QueueExecute {
@Autowired
QueueService queueRequest;
@Autowired
AsignService asignService;
@Autowired
CardService cardService;
@PostConstruct
public void init(){
new Thread(this::execute).start();
}
private void execute(){
while (true){
try {
RequestQueue request;
request = queueRequest.take();
if(request != null) {
List<Card> cards = cardService.processRequest(request.getSize(), new BigDecimal("1.0"));
request.getCards().setResult((ArrayList<Card>) cards);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
AssignService:
@Transactional
public void assignCards(DeferredResult<List<Card>> cards, Game game, Room room, Terminal terminal)
{
game = em.merge(game);
room = em.merge(room);
terminal = em.merge(terminal);
Order order = new Order();
LocalDateTime datetime = LocalDateTime.now();
BigDecimal total = new BigDecimal("0.0");
order.setTime(datetime)
order.setRoom(room);
order.setGame(game);
order.setId_terminal(terminal);
for(Card card: (List<Card>)cards.getResult()) {
card= em.merge(card)
--> System.out.println("CARD STATUS" + card.getStatus());
// This shows the OLD value of the Card (not updated)
card.setOrder(order);
order.getOrder().add(card);
}
game.setOrder(order);
//gameRepository.save(game)
}
С помощью этого кода он не сохраняет новый статус карты в БД, но Game, Terminal и Room хорошо сохраняются в БД (более или менее ...). Если я удалю assignService, CardService правильно сохраняет новый статус в БД.
Я пытался сбросить вручную, сохранить с помощью репо и так далее ... но результат почти тот же. Кто-нибудь может мне помочь?