Как ЗАБЛОКИРОВАТЬ СТОЛ ... делать вещи ... РАЗБЛОКИРОВАТЬ СТОЛ с помощью Spring Boot? - PullRequest
0 голосов
/ 10 июня 2019

Идея заключается в расширении некоторых репозиториев с пользовательскими функциями.Итак, я получил эту настройку, которая работает!

@MappedSuperclass
abstract class MyBaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Int = 0

    var eid: Int = 0

}

interface MyRepository<T : MyBaseEntity> {

    @Transactional
    fun saveInsert(entity: T): Optional<T>
}

open class MyRepositoryImpl<T : MyBaseEntity> : MyRepository<T> {

    @Autowired
    private lateinit var entityManager: EntityManager

    @Transactional
    override fun saveInsert(entity: T): Optional<T> {

        // lock table
        entityManager.createNativeQuery("LOCK TABLE myTable WRITE").executeUpdate()

        // get current max EID
        val result = entityManager.createNativeQuery("SELECT MAX(eid) FROM myTable LIMIT 1").singleResult as? Int ?: 0

        // set entities EID with incremented result
        entity.eid = result + 1

        // test if table is locked. sending manually 2-3 POST requests to REST
        Thread.sleep(5000)

        // save
        entityManager.persist(entity)

        // unlock
        entityManager.createNativeQuery("UNLOCK TABLES").executeUpdate()

        return Optional.of(entity)
    }
}

Как бы я сделал это более по-весеннему?

Сначала я подумал @Transactionalбудет делать блокировку и разблокировку вещи.Я попробовал пару дополнительных параметров и @Lock.Я просматривал документы и некоторые учебные пособия, но абстрактный технический английский часто нелегок для понимания.В конце концов, я не получил рабочее решение, поэтому я вручную добавил блокировку таблицы, которая отлично работает.Все же предпочел бы более весенний способ сделать это.

1 Ответ

0 голосов
/ 10 июня 2019

1) Также может быть проблема с вашим текущим дизайном. persist не сразу вставляет строку в базу данных. Это происходит при фиксации транзакции при возврате метода.

Таким образом, вы разблокируете таблицу перед фактической вставкой:

    // save
    entityManager.persist(entity) // -> There is no INSERT at this point.

    // unlock
    entityManager.createNativeQuery("UNLOCK TABLES").executeUpdate()

2) Возвращаясь к тому, как сделать это только с JPA без нативов (это все еще требует некоторого обходного решения, поскольку оно не поддерживается по умолчанию):

    // lock table by loading one existing entity and setting the LockModeType
    Entity lockedEntity = entityManager.find(Entity.class, 1, LockModeType.PESSIMISTIC_WRITE);

    // get current max EID, TRY NOT TO USE NATIVE QUERY HERE

    // set entities EID with incremented result

    // save
    entityManager.persist(entity)
    entityManager.flush() // -> Force an actual INSERT

    // unlock by passing the previous entity
    entityManager.lock(lockedEntity, LockModeType.NONE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...