Обработка мягких удалений с помощью Spring JPA

У меня есть таблица, определенная как …

 id, ..., active 

Active – это флаг soft-delete и всегда 1 или 0 . В долгосрочной перспективе это может уйти в пользу исторической таблицы.

 public interface StuffRepository extends JpaRepository {} 

В коде мы всегда используем активные записи. Есть ли способ заставить Spring всегда добавлять условие active=1 к запросам, сгенерированным для этого репозитория? Или, что еще лучше, позвольте мне расширить грамматику, используемую для генерации запросов?

Я понимаю, что я могу создавать named @queues всюду, но потом теряю удобство сгенерированных запросов. Я также хочу избежать загрязнения интерфейса «активными» методами.

Я использую Hibernate 4.2 в качестве моей реализации JPA, если это имеет значение.

Это старый вопрос, и вы, вероятно, уже нашли ответ. НО, для всех программистов Spring / JPA / Hibernate, ищущих ответа –

Скажем, у вас есть сущность. Собака:

  @Entity public class Dog{ ......(fields).... @Column(name="is_active") private Boolean active; } 

и хранилище:

 public interface DogRepository extends JpaRepository { } 

Все, что вам нужно сделать, это добавить аннотацию @Where на уровне сущности, в результате чего:

 @Entity @Where(clause="is_active=1") public class Dog{ ......(fields).... @Column(name="is_active") private Boolean active; } 

Все запросы, выполняемые репозиторием, будут автоматически отфильтровывать «неактивные» строки.

@Where(clause="is_active=1") – это не лучший способ обработки мягкого удаления с помощью весенних данных jpa.

Во-первых, он работает только с спящим режимом.

Во-вторых, вы никогда не сможете получать мягкие удаленные объекты с данными весны.

Мое решение задано с помощью весенних данных. Выражение #{#entityName} может использоваться для общего репозитория, представляющего конкретное имя типа объекта.

И код будет выглядеть так:

 //Override CrudRepository or PagingAndSortingRepository's query method: @Override @Query("select e from #{#entityName} e where e.deleteFlag=false") public List findAll(); //Look up deleted entities @Query("select e from #{#entityName} e where e.deleteFlag=true") public List recycleBin(); //Soft delete. @Query("update #{#entityName} e set e.deleteFlag=true where e.id=?1") @Modifying public void softDelete(String id); 

На основе 易天明 ответа я создал реализацию CrudRepository с помощью переопределенных методов для мягкого удаления:

 @NoRepositoryBean public interface SoftDeleteCrudRepository extends CrudRepository { @Override @Transactional(readOnly = true) @Query("select e from #{#entityName} e where e.isActive = true") List findAll(); @Override @Transactional(readOnly = true) @Query("select e from #{#entityName} e where e.id in ?1 and e.isActive = true") Iterable findAll(Iterable ids); @Override @Transactional(readOnly = true) @Query("select e from #{#entityName} e where e.id = ?1 and e.isActive = true") T findOne(ID id); //Look up deleted entities @Query("select e from #{#entityName} e where e.isActive = false") @Transactional(readOnly = true) List findInactive(); @Override @Transactional(readOnly = true) @Query("select count(e) from #{#entityName} e where e.isActive = true") long count(); @Override @Transactional(readOnly = true) default boolean exists(ID id) { return findOne(id) != null; } @Override @Query("update #{#entityName} e set e.isActive=false where e.id = ?1") @Transactional @Modifying void delete(Long id); @Override @Transactional default void delete(T entity) { delete(entity.getId()); } @Override @Transactional default void delete(Iterable entities) { entities.forEach(entitiy -> delete(entitiy.getId())); } @Override @Query("update #{#entityName} e set e.isActive=false") @Transactional @Modifying void deleteAll(); } 

Его можно использовать с BasicEntity:

 @MappedSuperclass public abstract class BasicEntity { @Column(name = "is_active") private boolean isActive = true; public abstract Long getId(); // isActive getters and setters... } 

И конечное лицо:

 @Entity @Table(name = "town") public class Town extends BasicEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "town_id_seq") @SequenceGenerator(name = "town_id_seq", sequenceName = "town_id_seq", allocationSize = 1) protected Long id; private String name; // getters and setters... } 

В текущих версиях (до 1.4.1) нет специальной поддержки для мягких удалений в Spring Data JPA. Тем не менее, я настоятельно рекомендую вам играть с ветвью функций для DATAJPA-307, поскольку это функция, которая в настоящее время работает для предстоящей версии.

Чтобы использовать текущее обновление состояния, вы используете версию 1.5.0.DATAJPA-307-SNAPSHOT и убедитесь, что вы разрешите ей использовать специальную версию Spring Data Commons, которую она должна работать. Вы должны быть в состоянии следовать образцу тестового примера, мы должны видеть, как заставить это работать.

PS: Я обновлю вопрос, как только мы закончим работу над этой функцией.

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

Вам также необходимо создать пользовательский JpaRepositoryFactoryBean и включить его в свой основной class.

Вы можете проверить мой код здесь https://github.com/dzinot/spring-boot-jpa-soft-delete

Я предлагаю вам использовать представление базы данных (или эквивалент в Oracle), если вы не хотите импортировать annotations спящего режима. В mySQL 5.5 эти представления могут быть обновляемыми и вставляемыми, если критерии фильтра просты, как активные = 1

создать или заменить view active_stuff как select * from Stuff, где active = 1;

Является ли это хорошей идеей, вероятно, зависит от вашей базы данных, но она отлично работает в моей реализации.

Undeleting требовал дополнительный объект, который напрямую обращался к «Stuff», но затем был бы @Where

  • Spring Data JPA: пакетная вставка для вложенных объектов
  • Данные Spring: поддерживается «delete by»?
  • Использование дженериков в репозиториях Spring Data JPA
  • Как добавить пользовательский метод в Spring Data JPA
  • Запрос репозитория динамической пружины jpa с произвольными предложениями AND
  • Как работает FetchMode в Spring Data JPA
  • Объединение двух элементов таблицы в Spring Data JPA
  • Spring-Data-Jpa Repository - Подчеркивание имени столбца объекта
  • ImprovedNamingStrategy больше не работает в Hibernate 5
  • Spring Data + JPA с несколькими источниками данных, но только один набор репозиториев
  • Может ли Spring Data REST использовать QueryDSL для выполнения более сложных запросов?
  • Interesting Posts

    Функция gets () в C

    Каков наилучший способ передать событие в ViewModel?

    Является TrueCrypt устойчивым к повреждению данных?

    Неявное преобразование из char ** в const char **

    Можно ли подключить подключенный сетевой диск из командной строки?

    Как отменить изменения, внесенные в Windows 10, «Уничтожить шпионаж Windows» (DWS_Lite.exe)

    Есть ли эквивалент Memtest86 для процессоров?

    ListView: TextView с LinkMovementMethod делает элемент списка незаметным?

    Какой пакетный файл окна позволяет записывать файлы ftp?

    Проверка с помощью Validating event и ErrorProvider – Показать сводку ошибок

    Как сделать высококачественный скриншот всей страницы в Firefox с помощью GCLI?

    Инструменты: заменить не замену в манифесте Android

    Добавить annotations данных к classу, сгенерированному инфраструктурой сущности

    Radeon 5500 с монитором Samsung – не получить полный экран?

    Пересылка определенных портов через реверсовые туннели SSH

    Давайте будем гением компьютера.