java - 如何使用 spring boot 和 jpa 一起软删除父级和子级(级联)

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

我有一个项目,不允许我删除记录。相反,我们通过更新数据库中的列(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 的删除标志被标记为 Y。但是,我希望与其关联的所有 SomeChildTable 也被软删除。

有办法实现这一点吗?我正在使用 spring data jpa。如果需要,请随时询问更多详细信息。

最佳答案

软删除不会传播,因为它不是默认存储库方法之一。您可以在此处查看界面:

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

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

@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(),那么您就会遇到问题。

还有一个与实体类上的 hibernate 一起使用的注释。

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

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

关于java - 如何使用 spring boot 和 jpa 一起软删除父级和子级(级联),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50525180/

相关文章:

java - 使用图形 Java 进行绘图的问题

java - 包含和删除列表中用户定义类实例的方法?

xml - tomcat7-maven-plugin log4j : no appender could be found for logger (org. apache.catalina.startup.Catalina)

spring - 如何在 Spring 3 中的 Controller 内生成 URI

java - Spring 中的命令对象

java - Spring引导+ Jersey API+JPA : failed to lazily initialize a collection of role

java - Java中的枚举查找

java - 如何决定一个对象是否应该成为聚合的一部分

java - 使用 servlet 上下文从 Spring Boot 应用程序获取资源的路径

java - Spring中使用@Async和@Scheduled时检测线程状态