2009-11-23 1 views
8

Мы используем реализацию Toplink JPA + Spring + EJB. В одном из наших EJBs мы имеем что-то вроде этого:JPA - сохранение изменений без persist() invoked

public void updateUser(long userId, String newName){ 
    User u = em.get(User.class, userId); 
    u.setName(newName); 
    // no persist is invoked here 
} 

Таким образом, в основном этот метод updateUser предполагается обновить имя пользователя с заданным идентификатором. Но автор этого метода забыл вызвать em.persist (u);

И самое странное, что все работает нормально. Как это может быть? Я был на 100% уверен, что без вызова em.persist() или em.merge() не может быть внесены изменения в базу данных. Могут ли они? Есть ли сценарий, когда это может произойти?

Thanks

ответ

11

Вы работаете с управляемым объектом. Если объект не отсоединяется, поскольку его диспетчер объектов закрыт, все изменения, сделанные для объекта, отражаются в базе данных, когда сеанс очищается/закрывается и транзакция завершается.

Java EE tutorial От:

состояние упорных сущностями синхронизируется с базой данных, когда сделка с которой компания является связанные фиксаций.

Редактировать для ясности и объяснения: Итак, есть три различных режима, что объект может быть в течение его жизненного цикла:

  • несохраненная: Субъект был экземпляр, но persist() не имеет еще называется.
  • Управляемый: Сущность была сохранена с использованием persist() или загружена из базы данных и связана с сеансом менеджера сущностей. Все изменения в объекте отражаются в базе данных при очистке сеанса менеджера объектов.
  • Персонал: Сессия менеджера сущности сущности была закрыта. Изменения в сущности не будут автоматически отражаться в базе данных, но могут быть объединены явно с помощью команды merge().
+0

Спасибо. Это очень помогло! Я всегда думал, что требуется вызов em.persist(), даже если объект связан с текущим EntityManager. – anthony

+0

Weird: В моей настройке у меня есть ссылка на управляемый объект. Затем я изменяю состояние этого объекта. Затем я вызываю 'entityManager.flush()'. В случае, если это выполняется в транзакции, тогда состояние изменения сущности ** записывается ** в базу данных. В случае, если это выполняется без транзакции, тогда измененное состояние объекта ** не записывается ** в базу данных. Так выглядит следующее утверждение: * «Всегда необходимо совершить транзакцию или вызов' entityManager.persist (obj) ', чтобы записать последнее состояние« obj »в базу данных.» * .... (Я использую JPA 2.0 с Hibernate (4.1.7.Final)) – Abdull

+0

@Abdull, да, спецификация JPA не определяет никакого поведения autocommit, поэтому вам нужна текущая транзакция или вообще ничего не записывается в базу данных. – Henning