Для начала создадим демонстрационный стенд с двумя сущностями User и AnObject, а так же DAO-слоем для них.
@Entity @Table(name = "user") public class User { @Id @GeneratedValue private long id; @Basic @Column(name = "username", updatable = false, unique = true, nullable = false) private String username; // getter and setter }
@Entity @Table(name = "anObject") public class AnObject { @Id @GeneratedValue private long id; @Column private String value; // getter and setter }
Добавим в сущность AnObject атрибут с двумя свойствами — дата последнего редактирования и автор правки:
@Embeddable public class LastModified { @Column @Temporal(TemporalType.TIMESTAMP) private Calendar lastUpdated; @OneToOne @JoinColumn(name = "lastEditor_id") private User lastEditor; // getter and setter }
public interface LastModifiable { LastModified getLastModified(); void setLastModified(LastModified modified); }
@Entity @Table(name = "anObject") public class AnObject implements LastModifiable { @Id @GeneratedValue private long id; @Column private String value; @Embedded private LastModified lastModified; // getter and setter }
И не забудем поправить тестовый класс с учётом нововведений.
С этого момента у нас уже есть всё необходимое для внесения данных о дате/авторе изменений в ручном режиме, но… люди мы «ленивые», поэтому давайте автоматизируем и эту работу — пусть за нас везде это делает Hibernate. Для этого добавляем Listener и просим Hibernate его использовать при возникновении события save или update (commit):
@Component public class LastModifiedListener extends DefaultSaveOrUpdateEventListener { private transient static final Logger LOG = LoggerFactory.getLogger(LastModifiedListener.class.getName()); @Autowired private UserDao userDao; @Override public void onSaveOrUpdate(SaveOrUpdateEvent event) { LOG.trace("object: {}", event.getObject()); if (event.getObject() instanceof LastModifiable) { LastModified lastModified = new LastModified((User) userDao.get(2)); ((LastModifiable) event.getObject()).setLastModified(lastModified); LOG.trace("object: {}", event.getObject()); } super.onSaveOrUpdate(event); } }
@Component public class HibernateEventWiring { @Autowired private SessionFactory sessionFactory; @Autowired private LastModifiedListener lastModifiedListener; @PostConstruct public void registerListeners() { EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService( EventListenerRegistry.class); registry.getEventListenerGroup(EventType.SAVE_UPDATE).prependListener(lastModifiedListener); } }
Теперь остался заключительный штрих — поправить тесты так, чтобы они учитывали новые изменения (хотя правильнее было бы сперва тесты поправить, а потом уже добавлять Listener)
На этом можно поставить финальную точку — у любой сущности, которая имплементирует интерфейс LastModifiable автоматически при каждом сохранении в БД будут изменяться поля lastUpdated и lastEditor.
ссылка на оригинал статьи http://habrahabr.ru/post/204854/
Добавить комментарий