如何处理 Spring 数据 JDBC 中的软删除?
How to handle soft-delete in Spring Data JDBC?
是否有处理 Spring 数据 JDBC 中的软删除的好方法?
在 Spring Data JPA 中,我们可以添加 @Where(clause="is_active=1")
注释或扩展 CrudRepository
或 PagingAndSortingRepository
.
由于 Spring 数据 JDBC 不支持查询中的 SPEL,我们不能像这样以通用方式编写它们:
@NoRepositoryBean
public interface SoftDeleteCrudRepository<T extends BasicEntity, ID extends
Long> extends CrudRepository<T, ID> {
//Override CrudRepository or PagingAndSortingRepository's query method:
@Override
@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.deleteFlag=false")
public List<T> findAll();
//Look up deleted entities
@Query("select e from #{#entityName} e where e.deleteFlag=true")
@Transactional(readOnly = true)
public List<T> findAllDeleted();
//Soft delete.
@Query("update #{#entityName} e set e.deleteFlag=true where e.id=?1")
@Transactional
@Modifying
public void softDelete(String id);
...
}
所以扩展 CrudRepository
或 PagingAndSortingRepository
意味着为每个 entity/table 的每个存储库编写相同的查询?喜欢
Repository1
@Override
@Transactional(readOnly = true)
@Query("select id, name, value, deleteFlag from table1 e where e.deleteFlag=false")
public List<T> findAll();
....
Repository2
@Override
@Transactional(readOnly = true)
@Query("select id, name, value, deleteFlag from table2 e where e.deleteFlag=false")
public List<T> findAll();
....
提前感谢您的回复!
我目前看到三个选项如何实现这一目标。
使用视图。为每个聚合根创建一个数据库视图,过滤掉软删除的行。根据这些视图映射您的实体。
写你自己的SqlGenerator
。并通过 SqlGeneratorSource
将其注入 DefaultDataAccessStrategy
。由于 SqlGenerator
仅对包可见,因此您必须为此创建自己的 DefaultDataAccessStrategy
,基本上是复制现有的。当然,这会带来长期的维护成本。
因为您的场景似乎只需要对实体名称的非常特殊的 SpEL 支持,为此打开一个问题并提交拉取请求可能是一个可行的选择。如果您对这种方法感兴趣并需要更多帮助,请在问题描述中提及。
@Dexter,我们在数据库中使用INT类型来标记记录的活动状态,如果使用布尔值,则可以修改StateTag枚举(可能是接口更好),然后调用changeState来改变状态。
delete or disable 是由业务服务层考虑的,像这样:
public class RoleServiceImpl extends SoftDeleteRepositoryServiceImpl<Role, Long>
implements RoleService {
private static final Logger LOGGER = LoggerFactory.getLogger(RoleServiceImpl.class);
.......
@Override
public Role deleteRole(Long roleId) {
return softDelete(roleId);
}
}
和
public class SoftDeleteRepositoryServiceImpl<T, ID extends Serializable> extends BasicRepositoryServiceImpl<T, ID>
implements SoftDeleteRepositoryService<T, ID> {
@Override
public T enable(ID id) {
return updateState(id, ENABLED);
}
........
@Override
public T softDelete(ID id) {
return updateState(id, DELETED);
}
}
是否有处理 Spring 数据 JDBC 中的软删除的好方法?
在 Spring Data JPA 中,我们可以添加 @Where(clause="is_active=1")
注释或扩展 CrudRepository
或 PagingAndSortingRepository
.
由于 Spring 数据 JDBC 不支持查询中的 SPEL,我们不能像这样以通用方式编写它们:
@NoRepositoryBean
public interface SoftDeleteCrudRepository<T extends BasicEntity, ID extends
Long> extends CrudRepository<T, ID> {
//Override CrudRepository or PagingAndSortingRepository's query method:
@Override
@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.deleteFlag=false")
public List<T> findAll();
//Look up deleted entities
@Query("select e from #{#entityName} e where e.deleteFlag=true")
@Transactional(readOnly = true)
public List<T> findAllDeleted();
//Soft delete.
@Query("update #{#entityName} e set e.deleteFlag=true where e.id=?1")
@Transactional
@Modifying
public void softDelete(String id);
...
}
所以扩展 CrudRepository
或 PagingAndSortingRepository
意味着为每个 entity/table 的每个存储库编写相同的查询?喜欢
Repository1
@Override
@Transactional(readOnly = true)
@Query("select id, name, value, deleteFlag from table1 e where e.deleteFlag=false")
public List<T> findAll();
....
Repository2
@Override
@Transactional(readOnly = true)
@Query("select id, name, value, deleteFlag from table2 e where e.deleteFlag=false")
public List<T> findAll();
....
提前感谢您的回复!
我目前看到三个选项如何实现这一目标。
使用视图。为每个聚合根创建一个数据库视图,过滤掉软删除的行。根据这些视图映射您的实体。
写你自己的
SqlGenerator
。并通过SqlGeneratorSource
将其注入DefaultDataAccessStrategy
。由于SqlGenerator
仅对包可见,因此您必须为此创建自己的DefaultDataAccessStrategy
,基本上是复制现有的。当然,这会带来长期的维护成本。因为您的场景似乎只需要对实体名称的非常特殊的 SpEL 支持,为此打开一个问题并提交拉取请求可能是一个可行的选择。如果您对这种方法感兴趣并需要更多帮助,请在问题描述中提及。
@Dexter,我们在数据库中使用INT类型来标记记录的活动状态,如果使用布尔值,则可以修改StateTag枚举(可能是接口更好),然后调用changeState来改变状态。 delete or disable 是由业务服务层考虑的,像这样:
public class RoleServiceImpl extends SoftDeleteRepositoryServiceImpl<Role, Long>
implements RoleService {
private static final Logger LOGGER = LoggerFactory.getLogger(RoleServiceImpl.class);
.......
@Override
public Role deleteRole(Long roleId) {
return softDelete(roleId);
}
}
和
public class SoftDeleteRepositoryServiceImpl<T, ID extends Serializable> extends BasicRepositoryServiceImpl<T, ID>
implements SoftDeleteRepositoryService<T, ID> {
@Override
public T enable(ID id) {
return updateState(id, ENABLED);
}
........
@Override
public T softDelete(ID id) {
return updateState(id, DELETED);
}
}