【问题标题】:How to soft delete parent and child together (cascade) using spring boot with jpa如何使用带有jpa的spring boot一起软删除父母和孩子(级联)
【发布时间】:2018-05-25 08:50:32
【问题描述】:

我有一个不允许删除记录的项目。相反,我们通过更新 db 中的列(deleteFlag)来软删除它们,这在所有实体中都很常见。我正在尝试以通用方式使用 JPA 来实现这一点,如果可能的话,我想要一个 JPA 解决方案。 deleteFlag 是软删除的标志,设置为 Y 或 N。

到目前为止我写的代码:

所有实体扩展的基类:

@MappedSuperclass
public class BaseEntity implements Serializable {

private static final long serialVersionUID = 1L;

@Column(name = "CREATED_BY_C")
private String createdByC;

@Column(name = "CREATED_DATE_DT", updatable = false, insertable = false)
private Timestamp createdDateDt;

@Column(name = "UPDATE_DATE_DT", updatable = false, insertable = false)
private Timestamp updateDateDt;

@Column(name = "UPDATED_BY_C")
private String updatedByC;

@Column(name = "DELETE_FLG")
private String deleteFlag;
//getters and setters

所有 CrudRepos 扩展的 BaseRepo:

    @NoRepositoryBean
    public interface BaseCrudRepository<T extends BaseEntity, ID extends Serializable>, CrudRepository<T, ID> {


    @Override
    @Query("select e from #{#entityName} e where e.deleteFlag !='Y'")
    public List<T> findAll();

    //Look up deleted entities
    @Query("select e from #{#entityName} e where e.deleteFlag ='Y'")
    public List<T> recycleBin(); 

    //Soft delete.
    @Query("update #{#entityName} e set e.deleteFlag='Y' where e.id=:id")
    @Modifying
    @Transactional
    public void softDelete(@Param("id")Integer id);     
}

我想要软删除的示例实体:

@Entity
@Table(name = "SOME_PARENT_TABLE", schema = "SOME_SCHEMA")
public class SomeParentTable extends BaseEntity {
private static final long serialVersionUID = 1L;

@Id
@Column(name = "id_field")
private Integer someParentTableId;

//more fields here

//bi-directional many-to-one association to SomeChildTable
@OneToMany(mappedBy = "sdIncomingTransaction", , cascade=CascadeType.ALL)
private List<SomeChildTable> someChildTables;

所以当我这样做时:

someParentTableRepository.softDelete(someParentTableId);

只有 someParentTable 的 deleteflag 被标记为 Y。但是,我希望与之关联的所有 SomeChildTable 也被软删除。

有没有办法做到这一点?我正在使用弹簧数据 jpa。如果需要,请随时询问更多详细信息。

【问题讨论】:

    标签: java spring spring-boot jpa spring-data-jpa


    【解决方案1】:

    软删除不会传播,因为它不是默认的存储库方法之一。你可以在这里查看接口:

    https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html

    所以 JPA 不会传播它,因为它是一些不属于接口的奇怪方法,Spring 不知道它。这就是为什么即使全部级联它也不会传播的原因。您应该重写 delete() 方法并使其执行软删除以符合接口。

    @Override
    @Query("update #{#entityName} e set e.deleteFlag='Y' where e.id=:id")
    @Modifying
    @Transactional
    public void delete(@Param("id")Integer id);     
    

    如果需要,请添加硬删除方法;)这是更好的解决方案,因为 delete() 是应在代码中调用的默认方法,并且应具有默认行为。否则在代码中的某个地方人们会习惯性地编写 delete() 而不是 softDelete() 并且你会遇到问题。

    还有这个注解可以在实体类上与休眠一起使用。

    @SQLDelete(sql = “UPDATE table SET deleteFlag= ‘Y’ WHERE id = ?”)
    

    我不确定确切的语法,但它会覆盖默认删除。我不确定它是否是 spring jpa 的一部分

    【讨论】:

    • @SQLDelete 是 Hibernate 注释。因此我不想使用它。
    • 是的,我相信另一种方法更好。只需使用默认的软删除实现覆盖 delete() 并在需要时创建一个方法 hardDelete()。
    • 我们不能像这样覆盖删除方法 bcoz CrudRepo 有 2 个删除方法 - 1 个接受要删除的对象,另一个接受 ID
    • 你可以 - 你覆盖两者。如果您只是添加一些方法 - 软删除或其他任何方法,那么 spring 将如何知道使用它?
    • 这也是我的 qstn。我如何帮助理解 Spring,当我说删除时,它不仅应该更新父表中的字段,还应该更新子表中的字段?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 1970-01-01
    • 2017-10-25
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    相关资源
    最近更新 更多