JPA EntityManager: сохранять объекты только при явном запросе

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

Глядя на некоторые базовые руководства по спящему режиму с использованием сеанса гибернации, я вижу, что могу сделать:

val session = HibernateUtil.getSessionFactory().getCurrentSession()
session.beginTransaction()
val coordinates = session.find(Coordinates::class.java, "12345")
coordinates.longitude = 0.0
session.save(coordinates)
session.getTransaction().commit()

При использовании Entitymanager это делается так:

val em = emFactory.createEntityManager()
em.transaction.begin()
val coordinates = em.find(Coordinates::class.java, "12345")
coordinates.longitude = 0.0
em.transaction.commit()

Основное отличие здесь в том, что при использовании EntityManager мне не нужно явно вызывать функцию save для фактического обновления объекта, который в конечном итоге будет сброшен во время фиксации. Конечно, я мог бы сделать что-то вроде

if(obj.id == null) {
    return em.merge()
} else {
    val saved = em.persist(obj)
    return saved
}

Но какой смысл в уже существующих объектах, если они все равно сохраняются, независимо от того, вызываю я это или нет?

Удивительно, но примеры можно найти здесь похоже, также полагаются на метод сохранения.

Мой вопрос: есть ли способ настроить EntityManager для обновления объектов только по запросу (т.е. имитировать поведение сеанса)? Или мне нужно использовать Session для достижения этого?


person xlecoustillier    schedule 29.05.2020    source источник
comment
Идея менеджера сущностей заключается в том, что он, как следует из его имени, управляет сущностями (которые привязаны к транзакции, в которой живет менеджер сущностей). Возможно, вам нужно объяснить вашу реальную проблему, чтобы мы могли понять, чего вы хотите достичь, вместо того, чтобы спрашивать о технических особенностях JPA. merge на EM можно использовать, например, для e. грамм. повторно присоединять объекты к сеансу без необходимости перезагрузки объекта и заполнения полей на основе отсоединенного объекта.   -  person Smutje    schedule 29.05.2020
comment
Я понимаю это, конечно. Моя проблема именно та, которую я описал: меня просят сохранять объекты только по запросу (т.е. вызов метода сохранения, что означает, что измененный объект должен быть отброшен, если он не сохранен явно). Я пытаюсь оценить, смогу ли я быстро исправить ситуацию, используя существующий EntityManager, или мне придется переключиться на использование сеанса, что будет стоить немного больше.   -  person xlecoustillier    schedule 29.05.2020
comment
Зачем вы меняете сущности, если не хотите, чтобы они менялись? ;-) Простой способ выйти из запроса, отбрасывая все изменения в JEE, - это выдать @ApplicationException(rollback=true), который, как предполагает его параметр, вызывает откат транзакции.   -  person Smutje    schedule 29.05.2020
comment
Но, тем не менее, моя точка зрения остается в силе: вы не упомянули, почему вы хотите отменить изменение объекта, а только то, что вам нужна такая возможность.   -  person Smutje    schedule 29.05.2020
comment
На самом деле причин несколько: бывают случаи, когда сущности модифицируются, но затем появляются бизнес-правила, требующие отмены этих изменений (вы можете сомневаться в правильности структуры кода, но пока она написана именно так). Еще один момент заключается в том, что этот код исходит из приложения, которое изначально не использовало СУБД (но использовало хранилище данных nosql), которое вообще не имело представления о контексте сохраняемости. Все это было абстрагировано за обычными вызовами CRUD, поэтому меня попросили по возможности сохранить то же поведение. Но я думаю, это ответ на мой вопрос :)   -  person xlecoustillier    schedule 29.05.2020


Ответы (1)


merge — это возможность для EntityManager фактически выполнять операции с базой данных. Слияние, сохранение, сброс и фиксация — это, по сути, все точки контакта с базой данных.

В простых случаях вы можете просто полагаться на изменение поведения при фиксации и не выполнять физическое слияние, но многим нравится, когда элемент управления знает, когда это произойдет на самом деле. Зная, что «после этого он в БД». Потому что после слияния сохраняются не только данные вместе с любым каскадным поведением, но и любые побочные эффекты от триггеров и т. д. в БД.

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

person Will Hartung    schedule 29.05.2020
comment
Я все это знаю, но спасибо за очень четкое объяснение :) - person xlecoustillier; 29.05.2020