Как найти идентификатор в контексте сохраняемости транзакций, если его нет в базе данных - PullRequest
0 голосов
/ 17 декабря 2018

Пример из Pro JPA:

@Stateless
public class AuditServiceBean implements AuditService {
    @PersistenceContext(unitName = "EmployeeService")
    EntityManager em;

    public void logTransaction(int empId, String action) {
        // verify employee number is valid
        if (em.find(Employee.class, empId) == null) {
            throw new IllegalArgumentException("Unknown employee id");
        }
        LogRecord lr = new LogRecord(empId, action);
        em.persist(lr);
    }
}

@Stateless
public class EmployeeServiceBean implements EmployeeService {
    @PersistenceContext(unitName = "EmployeeService")
    EntityManager em;
    @EJB
    AuditService audit;

    public void createEmployee(Employee emp) {
        em.persist(emp);
        audit.logTransaction(emp.getId(), "created employee");
    }
    // ...
}

И текст:

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

Насколько я понимаю, Id генерируется базой данных.Так как же можно emp.getId () передать в aud.logTransaction (), если транзакция еще не была зафиксирована и id еще не сгенерирован?

1 Ответ

0 голосов
/ 18 декабря 2018

зависит от стратегии GeneratedValue.если вы используете что-то вроде стратегии последовательности или таблицы.обычно провайдер персистентности присваивает идентификатор сущностям (у него есть некоторый зарезервированный идентификатор на основе размера выделения) сразу после вызова метода persist.

, но если вы используете идентификатор стратегии IDENTITY, другой провайдер может действовать по-разному.например, в hibernate, если вы используете стратегию идентификации, он немедленно выполняет оператор вставки и заполняет поле id объекта.

https://thoughts -on-java.org / jpa-generate-primary-keys / говорит:

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

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

https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Entities/Ids/GeneratedValue говорит:

Существует разница между использованиемIDENTITY и другие стратегии генерации идентификатора: идентификатор не будет доступен до тех пор, пока не произойдет вставка - именно операция вставки вызвала генерацию идентификатора.Из-за того, что вставка сущностей чаще всего откладывается до времени фиксации, идентификатор не будет доступен до тех пор, пока транзакция не будет сброшена или зафиксирована.

в реализации UnitOfWorkChangeSet имеет коллекцию для новыхсущности, которые не будут иметь реальной идентичности до вставки.

// This collection holds the new objects which will have no real identity until inserted.
    protected Map<Class, Map<ObjectChangeSet, ObjectChangeSet>> newObjectChangeSets;

JPA - Возврат автоматически сгенерированного идентификатора после persist () - это вопрос, связанный с eclipselink.

есть хорошие моменты в https://forum.hibernate.org/viewtopic.php?p=2384011#p2384011

Я в основном имею в виду некоторые замечания в Java Persistence с Hibernate.API Hibernate гарантирует, что после вызова save () у объекта будет назначенный идентификатор базы данных.В зависимости от типа генератора идентификаторов это означает, что Hibernate, возможно, должен будет выполнить инструкцию INSERT перед вызовом flush () или commit ().Это может вызвать проблемы во время отката.Это обсуждается на странице 490 Java Persistence с Hibernate.

В JPA persist () не возвращает идентификатор базы данных.По этой причине можно представить, что реализация задерживает генерацию идентификатора до времени сброса или фиксации.

На данный момент ваш подход может работать нормально, но вы можете столкнуться с проблемами при смене генератора идентификаторов или реализации JPA (переключение с Hibernate на что-то другое).

Может быть, это не проблема для вас, но я просто подумал, что я подниму это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...