Как идентифицировать объект временно или отключен в спящем режиме?

Я знаю, что переходный экземпляр означает, что экземпляр вновь создан, а соответствующая строка не существует в базе данных, где в качестве отдельного экземпляра есть соответствующая запись в базе данных, но не связанная с каким-либо сеансом в настоящее время.

Есть ли способ идентифицировать объект, который временно или отключен, используя любые методы на сеансе или что-то еще в спящем режиме программно?

Ответ 1

Похоже, вы ищете EntityManager#contains(Object).

Проверьте, является ли экземпляр экземпляром управляемого объекта, относящимся к текущему контексту персистентности.

Ответ 2

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

Если вы хотите проверить, не отсоединен ли он или преходящ (что вам не нужно, это должно быть прозрачно), вам нужно проверить, имеет ли данный объект ID.

if(data.getID() == null) return TRANSIENT;

Идентификатор должен быть установлен только для постоянных/отдельных объектов. Если по какой-то причине вы устанавливаете идентификатор самостоятельно на переходных объектах, тогда я не думаю, что вы хотите сделать.

Если вы не знаете, какое поле является идентификатором (по какой-либо причине) или вы хотите сделать его общим, вы можете попробовать:

ClassMetadata metadata = HibernateUtil.getSessionFactory().getClassMetadata(data.getClass());
if(metadata.getIdentifier(data) == null) return TRANSIENT;

Ответ 3

Чтобы проверить, находится ли объект e: -

  • Контекст сохранения: - EntityManager.contains(e) должен возвращать true.

  • Отдельное состояние: PersistenceUnitUtil.getIdentifier(e) возвращает значение свойства идентификатора сущностей.

  • Состояние переходного процесса: - PersistenceUnitUtil.getIdentifier(e) возвращает null

Вы можете перейти к PersistenceUnitUtil из EntityManagerFactory.

Есть два вопроса, на которые нужно обратить внимание. Во-первых, имейте в виду, что значение идентификатора может не быть назначенным и доступным до тех пор, пока контекст сохранения не будет сброшен. Во-вторых, спящий режим (в отличие от некоторых других поставщиков JPA) никогда не возвращает null из Persistence- UnitUtil # getIdentifier(), если ваше свойство идентификатора является примитивным (длинным и не a Long).

Ответ 4

Вы можете попробовать передать временный объект и отдельный объект в метод обновления сеанса гибернации и посмотреть на разницу. Для временного объекта hibernate сообщит об ошибке.

Таким образом, Hibernate знает, что объект является временным или отстраненным. Но как? Ответ прост: hibernate сделает выбор перед обновлением, чтобы получить информацию о том, какие поля являются грязными. Если объект временный, результат операции выбора не будет, тогда hibernate узнает, что это временный объект, и сообщит об ошибке.

Или, если вы используете @SelectBeforeUpdate(false), hibernate не будет делать выбор, вместо этого с непосредственным обновлением, в этом случае jdbc сообщит об ошибке, так как строки, которую нужно обновить, не существует.

Конечно, вы можете проверить поле id, если оно сгенерировано базой данных, или же единственный способ узнать его состояние - выполнить запрос: not found означает переходный процесс.

Ответ 5

Как говорили другие, в Hibernate можно использовать org.hibernate.Session.contains(Object) чтобы узнать, подключен или отключен экземпляр объекта. Что касается переходного состояния, я думаю, что лучшее, что можно сделать, - это то, что org.hibernate.Session.saveOrUpdate(Object) (благодаря org.hibernate.persister.entity.AbstractEntityPersister.isTransient(Object, SessionImplementor)), то есть:

  • если у объекта нет свойства @Id, оно всегда считается временным
  • если у сущности есть @Id свойства @Id равное null, оно всегда считается временным
  • если у сущности есть @Id свойства @Id равное сконфигурированному unsaved-value, то оно считается временным (применяется только к сопоставлению XML, я думаю, что это несколько устарело, см. здесь)
  • если он имеет @Version свойства, значение которого является один из недавно созданного экземпляра (то есть, это null Long, или Date и т.д.), то он считается переходным

Следовательно, я думаю, что для сущностей без сгенерированного идентификатора, поиск свойства @Version - это путь. Если такого свойства нет, сама Hibernate в saveOrUpdate выполняет запрос SELECT к базе данных, чтобы определить, является ли экземпляр объекта временным или нет, чтобы определить, следует ли ему выполнить INSERT или UPDATE соответственно.

См. Руководство по Hibernate (например, 4.3 здесь).