当前位置: 首页 > 知识库问答 >
问题:

如果在没有刷新的情况下进行添加和删除,则删除不会删除

斜昊空
2023-03-14

我只是想了解SpringJPA/Hibernate的某些部分是如何工作的。正如标题所说,只有在从集合中添加和删除子实体之间将实体刷新到数据库时,删除孤儿似乎才起作用,我想知道为什么。

我有一个父类,它与一个子类有一个@OneToMore关联

@Entity
class Parent {
    
    @Id
    @GeneratedValue
    @Getter
    private Long id;
    
    @OneToMany(mappedBy = parent, cascade=ALL, orphanRemoval=true)
    @Getter
    private Set<Child> children;
    
    public Parent(){
        children = new HashSet<Child>();
    }

    public Child addChild(Child child){
        child.setParent(this);
        children.add(child);
        return child;
    }

    public void removeChild(Child child){
        child.setParent(null);
        children.remove(child);
    }
}

@Entity
class Child {

    @Id
    @GeneratedValue
    @Getter
    private Long id;

    @ManyToOne
    @Setter
    private Parent parent;
}
        

我正在测试让孩子在从父级删除时删除,就像这样(使用@autowiledJPARepository

@ExtendWith(SpringExtension.class)
@DataJpaTest
class PersistTest {
    
    @Autowired ParentRepository repo; // JpaRepository<Parent, Long>
    @Autowired EntityManager em;

    @Test
    public void whenChildRemoved_thenChildDeleted(){
        Parent parent = new Parent();
        Child child = parent.addChild(new Child());
        repo.save(parent);

        em.flush(); // test fails if removed

        parent.removeChild(child);
        repo.saveAndFlush(parent);
        
        assertThat(repo.findById(parent.getId()).get().getChildren()).isEmpty();
        assertThat(em.find(Child.class, child.getId()).isNull();
    }
}

如果在将子项添加到父项和删除子项之间未刷新实体管理器,则两个断言都会失败,并且在查看生成的sql时,不会执行DELETE语句。如果EM被刷新,则进行删除,测试通过。

基本上只是想知道是否有人可以解释为什么会出现这种情况,以及将这两个操作放在单独的@Transactional方法中是否会产生相同的效果。

共有1个答案

汝飞
2023-03-14

您期望完成或创建一些事务,但实际上并没有。这就是为什么你会看到这种行为。

  1. @DataJpaTest在每个方法上放置单独的事务(默认情况下会回滚)
  2. 这就是为什么您可以使用JpaRepository——它不创建事务本身(与crudepository相反),但有一个底层事务
  3. 如果JpaRepository使用了@Transactional(必需\u NEW),您可以删除flush

回答你最后一个问题。如果您将这些操作放在单独的@Transactional方法中,它将以完全相同的方式工作,因为在由@DataJpaTest创建的测试中存在底层事务-hibernate通常会在方法的最后刷新...您必须使用@Transactional(REQUIRED_NEW)

 类似资料:
  • 有没有什么方法可以动态编辑加载到Drools中的规则,而不需要重新加载新的DRL文件? 我们试图使用Drools作为规则引擎,但在我们的用例中,规则的添加和删除非常频繁,我们希望避免每次发生这种情况时都必须重新加载整个.drl文件。

  • (示例代码张贴在末尾。) 我正在使用EF Core 5数据库优先(即逆向工程POCO)。当使用,后续的抱怨孤儿。是的,很多问 对于代码优先方案,可以将其添加到配置中(从这里): 但首先对DB来说是不现实的。如果数据库为FK关系(此处的文档引用)设置了级联删除,则生成的模型[更正]不包括 并且删除(使用)确实有效,包括。但是... 我在这里面临的问题是,这个“解决方案”要求我们的所有FK关系都在数据

  • 是否可以从索引中删除单个映射类型而不删除整个索引?https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-delete-mapping.html说这已经不可能了,但我觉得这很难相信。有人能解释为什么删除了该功能吗?似乎是基本的东西。 我有一个具有两个映射的索引。我希望能够删除一种映射类型(以及该类型的所有文档)

  • 问题内容: 我有一个脚本,它使用DROP TABLE IF EXISTS删除表的负载,这可以工作。 此脚本中还有一个删除操作,用于从我不管理的另一个表中删除一行。该表可能存在或不存在。是否有任何在尝试删除行之前检查该表是否存在? 这需要适用于MYSQL和SQLServer 谢谢亚历克斯 问题答案: 要签入SQL SERVER, 要检查mysql: 您只需数:

  • 我正在建立一个应用程序,并使用MariaDB作为我的数据库。我有一张桌子“kick_votes”。其主键包含三个字段: null

  • ADDING AND REMOVING SOFTWARE Linux 或任何操作系统中最基本的任务之一便是添加和删除软件。您经常需要安装发行版中没有附带的软件,或者删除不需要的软件,这样就不会占用硬盘空间。 有些软件安装需要依赖其他软件才能运行,有时您会发现您可以在软件包安装过程中一次性下载所需的所有软件,软件包是一组文件(通常是库和其他依赖项),您需要这些文件才能使软件成功运行。当您安装一个包时