Я столкнулся с той же проблемой; Я должен обновить сумму кредита, и должен получить измененное время, вместе с деталями кредита из БД. Это в основном
СИНХРОННО / АТОМНО выполнить (ОБНОВИТЬ, затем ПОЛУЧИТЬ) в MYSQL
Я перепробовал много вариантов и нашел один, который решил мою проблему.
1) OPTION_1 ВЫБРАТЬ ОБНОВЛЕНИЕ
Это сохранение блокировки до обновления (SYNC от GET до UPDATE), но мне нужна блокировка после обновления до GET.
2) OPTION_2 Хранимая процедура
Хранимая процедура не будет выполняться синхронно, как redis lua, поэтому для этого также необходим код синхронизации.
3) OPTION_3 Транзакция
Я использовал JPA entityManager, как показано ниже, думал, что до коммита никто не сможет обновить, а до коммита я получу обновленный объект вместе с измененным временем (из БД). Но я не получил последний объект. Только коммит я получил последний.
try {
entityManager.getTransaction().begin();
//entityManager.persist(object);
int upsert = entityManager.createNativeQuery(
"update com.bill.Credit c set c.balance = c.balance - ?1
where c.accountId = ?2 and c.balance >= ?1").executeUpdate();
//c.balance >= ? for limit check
Credit newCredit = entityManager.find(Credit.class, "id");
entityManager.refresh(newCredit); //SHOULD GET LATEST BUT NOT
entityManager.getTransaction().commit();
} finally {
entityManager.unwrap(Session.class).close();
}
4) OPTION_4 LOCK решил проблему, поэтому перед обновлением я получил блокировку; затем после GET я снял блокировку.
private Object getLock(final EntityManager entityManager, final String Id){
entityManager.getTransaction().begin();
Object obj_acquire = entityManager.createNativeQuery("SELECT GET_LOCK('" + Id + "', 10)").getSingleResult();
entityManager.getTransaction().commit();
return obj_acquire;
}
private Object releaseLock(final EntityManager entityManager, final String Id){
entityManager.getTransaction().begin();
Object obj_release = entityManager.createNativeQuery("SELECT RELEASE_LOCK('" + Id + "')").getSingleResult();
entityManager.getTransaction().commit();
return obj_release;
}