简体   繁体   English

如何在Spring Data JDBC中处理软删除?

[英]How to handle soft-delete in Spring Data JDBC?

Is there a good way of how to handle soft-delete in Spring Data JDBC? 有没有一种很好的方法来处理Spring Data JDBC中的软删除?

In Spring Data JPA we can either add @Where(clause="is_active=1") annotation or extend CrudRepository or PagingAndSortingRepository . 在Spring Data JPA中,我们可以添加@Where(clause="is_active=1")注释或扩展CrudRepositoryPagingAndSortingRepository

Since Spring Data JDBC doesn't support SPEL in queries, we cant write them in generic way like this: 由于Spring Data 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);
...
}

So extending CrudRepository or PagingAndSortingRepository means writing same queries for each repository for each entity/table? 因此,扩展CrudRepositoryPagingAndSortingRepository意味着为每个实体/表的每个存储库编写相同的查询? Like 喜欢

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();
....

Thank you for the reply in advance! 感谢您提前回复!

I currently see three options how one might achieve this. 我目前看到三个选项如何实现这一目标。

  1. Use views. 使用视图。 For each aggregate root create a database view that filters out the soft-deleted rows. 对于每个聚合根,创建一个数据库视图,用于筛选出软删除的行。 Map your entities against these views. 根据这些视图映射您的实体。

  2. write your own SqlGenerator . 编写自己的SqlGenerator And inject it into the DefaultDataAccessStrategy via a SqlGeneratorSource . 并通过SqlGeneratorSource将其注入DefaultDataAccessStrategy Since SqlGenerator is only package-visible you'll have to create your own DefaultDataAccessStrategy for this basically duplicating the existing one. 由于SqlGenerator只是包可见,因此您必须为此创建自己的DefaultDataAccessStrategy ,基本上复制现有的版本。 This, of course, will come with a long-term cost of maintaining it. 当然,这将带来维持它的长期成本。

  3. Since all you seem to need for your scenario is the very special SpEL support for the entity name opening an issue for that and submitting a pull request might be a viable option. 由于您的场景似乎需要的是对实体名称的非常​​特殊的SpEL支持,因此为此提出问题并提交拉取请求可能是一个可行的选择。 If you are interested in this approach and need more help with it mention it in the issue description. 如果您对此方法感兴趣并需要更多帮助,请在问题说明中提及它。

@Dexter, we use a INT type in db to flag a record's active state, if you use boolean,you can modify StateTag enum(may be interface better), then call changeState to change the state. @Dexter,我们在db中使用INT类型来标记记录的活动状态,如果使用boolean,则可以修改StateTag枚举(可能是接口更好),然后调用changeState来改变状态。 delete or disable is considered by business service layer,like this: 业务服务层考虑删除或禁用,如下所示:

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

} }

and

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM