Подтвердить что ты не робот

Как проверить, загрязнен ли объект в Hibernate?

Как проверить, находится ли объект в Hibernate в грязном состоянии? То есть Я хочу установить UpdatedBy и UpdatedAt только в том случае, если какое-то поле изменилось. Таким образом, я могу проверить объект вручную, сравнивая каждое поле в двух объектах, но может ли быть еще более элегантный способ сделать это?

Кроме того, hibernate делает entity dirty, если я устанавливаю для поля объекта то же значение, что и раньше? То есть:.

String name = myEntity.getName()
myEntity.setName(name);

EDIT:

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

4b9b3361

Ответ 1

Отличный вопрос, это короткий ответ: Hibernate-Session имеет метод isDirty()

Длинный ответ с примером (ТЕСТИРОВАНИЕ CASE 1):

Если вы используете Seam/POJOs/JPA поверх Hibernate. вы хотели бы знать, какие сущности грязны перед вызовом entityManager.flush() - то есть знать, для каких объектов Hibernate будет выдавать инструкцию update - и применять некоторые изменения в этих записях (установить некоторые значения, например, кто изменил запись и т.д.),.

вы знаете, что в Hibernate-Session есть метод isDirty(), но в некоторых случаях этого недостаточно.

вы можете зарегистрировать Hibernate-Interceptor в файле persistence.xml

     <property name="hibernate.ejb.interceptor" value="path.to.MyInterceptor" />  

и перехватите метод onFlushDirty (...) и сохраните грязные объекты на карте, но как я могу получить доступ к этой карте позже? У меня нет доступа к перехватчику во время выполнения (чтобы я мог вызвать interceptor.getDirtyEntities()), у вас есть это:

public class MyInterceptor extends EmptyInterceptor {  
         private Map<IdentityKey,Object> dirtyEntitiesMap = new HashMap<IdentityKey,Object>();  

     @Override  
     public boolean onFlushDirty(Object entity, Serializable id,  
               Object[] currentState, Object[] previousState,  
               String[] propertyNames, Type[] types) {  

           dirtyEntitiesMap.put(new IdentityKey(id, entity.getClass()), entity);    
           return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);  
     }  
...  
}  

SOLVER ЭТОТ ИСПЫТАТЕЛЬНЫЙ СЛУЧАЙ: Вам не нужно знать, какие объекты меняются, если вам нужно их обновить. Вы можете добавить свой код (заполнив пользователя, который их изменил) в методе @PreUpdate. Объекты, которые являются грязными, будут соответствующим образом изменены, те, которые не являются, не получат этот метод, потому что ничего не обновлять (и Hibernate обнаружит это). Вы можете сделать то же самое для новых объектов в методе @PrePersist, который, вероятно, идентичен. Вы можете аннотировать тот же метод с обоими.

Если вам также необходимо записать, какие поля были изменены, я бы предложил сначала посмотреть на Envers.

Ответ 2

onFlushDirty (...) метод работает для меня, чтобы проверить грязную коллекцию. Родительский объект с вложенной коллекцией передается в onFlushDirty, но я не знал, что переданный объект может быть элементом коллекции. Как только я нашел это, он работал как для вложенной коллекции, так и для ее родительского объекта.

public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types)

Другой метод onCollectionUpdate (...) также может использоваться для сбора грязной коллекции, он вызывается после onFlushDirty (...).

Ответ 3

Зачем нужно время от времени? Я предлагаю просто удалить сущность

getEntityManager().detach(myEntity)

и посмотреть свое постоянное представление из БД, и вы можете решить если соответствующие поля изменились, чтобы вы могли создать новую версию. По крайней мере, убедитесь, что этот объект загрязнен:)