gpt4 book ai didi

java - orphanRemoval 在 PostgreSQL 中工作但在 hsqldb 中不工作

转载 作者:行者123 更新时间:2023-11-29 12:04:52 26 4
gpt4 key购买 nike

我有 Academy 实体:

@Entity
@Table(name = "academy")
public class Academy {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private String name;

@Column(nullable = false)
private String address;

@OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "parent")
private List<Institute> institutes;

public Academy() {}

public Academy(String name, String address, List<Institute> institutes) {
this.name = name;
this.address = address;
this.institutes = institutes;
}

Institute实体:

@Entity
@Table(name = "institute")
public class Institute {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
private String name;

@Column(name = "building_code")
private String buildingCode;

@ManyToOne(optional = false)
private Academy parent;

@OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "parent")
private List<Department> departments;


public Institute() {}

public Institute(String name, String buildingCode, Academy parent, List<Department> departments) {
this.name = name;
this.buildingCode = buildingCode;
this.parent = parent;
this.departments = departments;

parent.getInstitutes().add(this);
}

Academy 是父级,Institute 是子级(树状结构)。 InstituteDepartment - 但此时并不重要。我正在使用 orphanRemoval = trueAcademy 被删除时删除所有 Academy child (学院等...)(类 UnitServiceImpl. java):

@Override
@Transactional
public String remove(String whatIsRemoved, Long id) {
if (whatIsRemoved.equals("academy")){
Academy academy = getAcademyById(id);
academy.getInstitutes().clear();
getCurrentSession().delete(academy);
}
else if (whatIsRemoved.equals("institute")){
Institute institute = getInstituteById(id);
institute.getParent().getInstitutes().remove(institute);
}
//other if's etc..
}

当我使用应用程序时,一切似乎都正常 - 当我删除 Academy 时,每个 Institute 都与这个 Academy 和他的相关Department 等从数据库中删除(我使用的是 PostgreSQL 9.3)。简而言之 - 它表现为树状结构。但是如果我尝试用内存数据库编写单元测试(我在 2.3.2 版本中使用 hsqldb)应该证明这一点:

@Test
@Transactional
public void test_WhenAcademyWasRemoved_InstitutesAlsoShouldBeRemoved() throws Exception {
UnitServiceImpl service = new UnitServiceImpl();
service.setSessionFactory(sessionFactory);

AcademyDTO michigan = new AcademyDTO(null, "Michigan", "test");
service.saveAcademy(michigan);
service.saveInstitute(new InstituteDTO(null, "IT", "D", getAcademyIdByName(service, "Michigan"), null));
service.remove("academy", getAcademyIdByName(service, "Michigan"));

List<Institute> institutes = (List<Institute>)sessionFactory.getCurrentSession().createCriteria(Institute.class).list();
assertEquals(0, institutes.size());
}

与“Michigan”相关的机构仍在以“Michigan”为父级的数据库中,并且测试崩溃。这意味着我错了,在 PostgreSQL 数据库中它们也没有被删除(但我检查了一下,Instututes 是空的)?或者,这仅意味着它们将在 Transaction 提交时被删除?因为测试方法需要是@Transactional,没有它测试将无法编译——但是,如何测试呢?我被卡住了,因为在应用程序中它看起来不错,但在内存数据库的单元测试中它不能像我认为的那样工作。如果有人帮助我,我将非常高兴 - 在此先感谢您。更新: 问题是:orphanRemoval = true在本地主机数据库上工作,在我看来,因为事务已提交,然后应用了级联删除。我怎样才能在单元测试中以不太复杂的方式做同样的事情 - 比如在测试结束之前提交事务(触发级联删除),然后用另一个 Transaction 获取 Institute ?我在测试中尝试了私有(private) @Transactional 方法,但它不起作用。

最佳答案

我认为问题可能在于测试中的事务处理方式与“正常”代码中的处理方式不同(这让我一遍又一遍地感到困惑)。

让我们验证一下我是否正确理解您的问题:

当您使用 mysql 数据库运行应用程序时,一切正常。

但是当您针对 hsqldb 级联删除运行测试时似乎失败了。

我认为这两种情况的区别在于事务的处理,更重要的是更改从 session 刷新到数据库的时间,即实际执行的 sql 语句。

要验证这一点,您可以激活 sql 日志记录以查看您的数据何时准确存储在数据库中。我的期望是,在生产中,这最晚发生在每个 @Transactional 方法的末尾,但在测试中,由于测试中的 @Transactional 注释,所有内容都在单个事务中运行,并且不会发生刷新,或者至少不会同时发生时间点。

为了模拟生产行为,您可以在通常事务结束的地方添加对 Session.flush 的调用。

关于java - orphanRemoval 在 PostgreSQL 中工作但在 hsqldb 中不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30156908/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com