Как объект получает идентификатор до совершения транзакции в JPA/Play?

См. этот вопрос.

Оказывается, что даже без совершения транзакции вручную, перед передачей TX, у человека есть идентификатор после вызова метода save().

Разве база данных не отвечает за определение поля ID? Если да, как можно заполнить поле ID перед фиксацией? Происходит ли какое-либо сообщение с БД до передачи TX?

Ответ 1

Да, JPA разрешено связываться с БД до совершения транзакции. Это может произойти, например, когда вы явно вызываете EntityManager#flush().

Кроме того, провайдеру JPA разрешено выполнять флеш-операцию всякий раз, когда он считает это необходимым. Однако, по удобству, поставщики JPA задерживают операции БД до момента совершения транзакции.

Некоторые стратегии автоматического генератора идентификаторов должны попасть в базу данных, чтобы получить значение PK (насколько я помню, стратегия IDENTITY работает таким образом).
Как обратное, генераторам TABLE или SEQUENCE нет необходимости в попадании в БД для получения значения ID. Они используют параметр allocationSize, чтобы спросить DB TABLE или SEQUENCE для пакетных идентификаторов, которые будут переданы новым сущностям без дальнейшей связи с базой данных.

Ответ 2

Играть! (который записывает изменения в базу данных и позволяет получить сгенерированный идентификатор) каждый раз, когда вы сохраняете объект, используя метод save() для модели:

Из исходного кода JPABase._save():

if (!em().contains(this)) {
    em().persist(this);
    PlayPlugin.postEvent("JPASupport.objectPersisted", this);
}
// ...
try {
    em().flush();
} catch (PersistenceException e) {
    // ...
}

Ответ 3

как я знаю, мы не сможем получить идентификатор объекта (предположим, что он пронумерован автоматически) до его сохранения. и я лично считаю, что довольно опасно назначать что-то, что должно быть сделано СУРБД вне его.

Ответ 4

Взаимодействие между инициалами и фиксацией, после вызова метода сохранения или обновления, вы должны использовать:

EntityManagerHelper.getEntityManager().flush();

Если вы его не назовете, объект будет потерян и не может быть сохранен в БД.

Итак, после его вызова вы будете использовать id объекта в объекте.