Manejo de borrado suave con Spring JPA

Tengo una tabla Stuff definidas como …

 id, ..., active 

Active es la bandera de borrado suave y siempre es 1 o 0 . A largo plazo esto puede desaparecer a favor de una tabla histórica.

 public interface StuffRepository extends JpaRepository {} 

En el código, siempre usamos registros activos. ¿Hay alguna manera de hacer que Spring añada siempre una condición active=1 a las consultas generadas para este repository? ¿O más idealmente, permítame extender la gramática utilizada para generar las consultas?

Entiendo que puedo crear @queues nombre en todas partes, pero luego pierdo la comodidad de las consultas generadas. También quiero evitar contaminar la interfaz con métodos “activos”.

Estoy utilizando Hibernate 4.2 como mi implementación de JPA si eso es importante.

Esta es una vieja pregunta, y probablemente ya encontraste la respuesta. PERO, para todos los progtwigdores de Spring / JPA / Hibernate que buscan respuesta –

Digamos que tienes una entidad Dog:

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

y un repository

 public interface DogRepository extends JpaRepository { } 

Todo lo que necesita hacer es agregar la anotación @Where en el nivel de la entidad, lo que da como resultado:

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

Todas las consultas realizadas por el repository filtrarán automáticamente las filas “no activas”.

@Where(clause="is_active=1") no es la mejor manera de manejar la eliminación suave con datos de spring jpa.

En primer lugar, solo funciona con el instrumento de hibernación.

En segundo lugar, nunca puede buscar entidades eliminadas con datos de spring.

Mi solución es el proporcionado por los datos de spring. #{#entityName} expresión #{#entityName} se puede usar en un repository genérico para representar el nombre del tipo de entidad concreta.

Y el código será así:

 //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); 

Basado en la respuesta I, he creado la implementación CrudRepository con métodos modificados para la eliminación suave:

 @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< ? extends T> entities) { entities.forEach(entitiy -> delete(entitiy.getId())); } @Override @Query("update #{#entityName} e set e.isActive=false") @Transactional @Modifying void deleteAll(); } 

Se puede usar con BasicEntity:

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

Y entidad final:

 @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... } 

En las versiones actuales (hasta 1.4.1) no hay soporte dedicado para eliminaciones suaves en Spring Data JPA. Sin embargo, le recomiendo encarecidamente que juegue con la twig de características para DATAJPA-307 ya que esta es una función actualmente trabajada para la próxima versión.

Para usar el estado actual, actualice la versión que usa a 1.5.0.DATAJPA-307-SNAPSHOT y asegúrese de dejar que se aplique la versión especial Spring Data Commons que necesita para funcionar. Debería poder seguir el caso de prueba de muestra que tenemos para ver cómo hacer que esas cosas funcionen.

PD: Actualizaré la pregunta una vez que hayamos terminado de trabajar en la función.

Puede extender desde SimpleJpaRepository y crear su propio repository personalizado donde puede definir la funcionalidad de borrado suave de una manera genérica.

También necesitarás crear un JpaRepositoryFactoryBean personalizado y habilitarlo en tu clase principal.

Puedes consultar mi código aquí https://github.com/dzinot/spring-boot-jpa-soft-delete

Sugiero que use una vista de base de datos (o equivalente en Oracle) si no desea importar anotaciones específicas de hibernación. En mySQL 5.5, estas vistas pueden ser actualizadas e insertables si el criterio de filtro es tan simple como activo = 1

crear o reemplazar ver active_stuff como select * from Stuff donde active = 1;

Si esta es una buena idea, probablemente dependa de su base de datos, pero funciona muy bien en mi implementación.

La desactivación requirió una entidad adicional que accedió a ‘Cosas’ directamente, pero también lo haría @Where