Spring JPA транзакция с пулом потоков - PullRequest
0 голосов
/ 20 октября 2018

Я пытаюсь понять, почему приведенный ниже фрагмент кода не работает должным образом.

У меня уже есть customer с id=1234 and name=A1.Я создаю 2 вызываемые задачи и прошу их выполнить transnational update метод.

Обе транзакции выполняются вместе (так как я ввел 1 секунду задержки после чтения копии клиента из базы данных, как показано в коде) и прочитал оригинального клиента с помощью id=1234 and name=A1

Один пытается update name from A1->A2 и другие попытки update name from A1->A3

Я ожидал, что по крайней мере 1 транзакция вызовет исключение конфликта / устаревших данных при фиксации, но в обоих случаях оба успешно завершатся.

Не могли бы вы помочь мне понять это?Что ж?Я что-то упускаю концептуально?

Main.java

    @Autowired
    CustomerService service;

    // Update address from A1 to A2
    Callable<String> t1 = new Callable<String>() {

        @Override
        public String call() throws Exception {
            service.updateCustomer("1234", "A2");
            return "T1 Done";
        }
    };

    // Update address from A1 to A3
    Callable<String> t2 = new Callable<String>() {

        @Override
        public String call() throws Exception {
            service.updateCustomer("1234", "A3");
            return "T2 Done";
        }
    };

    ExecutorService executorService = Executors.newFixedThreadPool(2);
    executorService.invokeAll((Collection) Arrays.asList(t1, t2));

CustomerService.java

@Transactional
public void updateCustomer(String customerId, String customerName) {
    try {
        Optional<Customer> currentCopyHandle = repo.findById(customerId);
        Customer currentCopy = currentCopyHandle.get();

        Thread.sleep(1000);

        ObjectMapper mapper = new ObjectMapper();

        String customerDetails = currentCopy.getDetails();

        ObjectNode writableDetails = (ObjectNode) mapper.readTree(customerDetails);
        writableDetails.put("name", customerName);

        currentCopy.setDetails(mapper.writeValueAsString(writableDetails));

        repo.save(currentCopy);

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Редактировать-1 Customer.java

Это POJO, совместимый с Oracle 12c, где поле с именем details помечено как @Lob, а таблица oracle12c имеет ограничение json

@Entity
public class Customer {

@Id
@javax.persistence.Id
private String cid;

@Lob
private String details;

public Customer() {
}

@PersistenceConstructor
public Customer(String cid, String details) {
    super();
    this.cid = cid;
    this.details = details;
}

public String getCid() {
    return cid;
}

public void setCid(String cid) {
    this.cid = cid;
}

public String getDetails() {
    return details;
}

public void setDetails(String details) {
    this.details = details;
}
}

До того, как я начал это упражнениеЯ сделал ниже деятельности.

String json = "{ \"cid\" : \"1234\", \"name\" : \"A1\", \"address\" : \"India\"}";

service.saveCustomer1(new Customer("1234", json));

1 Ответ

0 голосов
/ 20 октября 2018

Спасибо JBNizet !

Использование оптимистической блокировки путем добавления свойства @Version к моей модели решило мою проблему.

...