gpt4 book ai didi

java - Spring 启动 hibernate : cannot delete child object separately

转载 作者:行者123 更新时间:2023-12-03 23:14:52 25 4
gpt4 key购买 nike

我有一个简单的设置,包含两个对象,EventTask,它们作为父子链接,以及用于某些 CRUD 操作的默认 JPA 存储库。我做了一个测试,我将 2 个 Task 附加到一个 Event,然后我尝试对其中一个 调用一个 delete 操作>Task,失败(没有错误,也没有删除)。

如果我在未将 Task 添加到 Event 的情况下运行相同的测试,则操作会成功。我的所有代码都在下面,对我下一步需要做什么有什么想法吗?

@Entity
public class Event {

@Id
@GeneratedValue(generator = "hibernate-uuid")
@GenericGenerator(name = "hibernate-uuid", strategy = "uuid2")
@Column(unique = true)
String id;

String subject;

@OneToMany(mappedBy="event", cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
@JsonIgnoreProperties({"event"})
List<Task> tasks;
}

@Entity
public class Task {
@Id
@GeneratedValue(generator = "hibernate-uuid")
@GenericGenerator(name = "hibernate-uuid", strategy = "uuid2")
@Column(unique = true)
String id;

String subject;

@ManyToOne
@JsonIgnoreProperties({"tasks"})
Event event;
}

public interface TaskRepository extends JpaRepository<Task, String> {
public Task findById(String id);
}

和测试:

@Test
public void testSequenceOfActionsOnEventWithSubtasks() {
// Save a new task
Task savedTask = given()
.body(
new TaskBuilder()
.subject("Previously saved task")
.build()
).contentType(ContentType.JSON)
.when().post(TASKS_RESOURCE).as(Task.class);


Task unsavedTask = new TaskBuilder()
.subject("Unsaved task")
.build();


// Save a new event with an unsaved and a saved task attached
Event savedEvent = given()
.body(
new EventBuilder()
.subject("Main event")
.addTask(savedTask)
.addTask(unsavedTask)
.build()
).contentType(ContentType.JSON)
.when().post(EVENTS_RESOURCE).as(Event.class);


// Make sure the event now contains two tasks with GUID's attached
List<Task> tasksForEvent = when().get(EVENT_RESOURCE, savedEvent.getId()).as(Event.class).getTasks();
assertEquals(2, tasksForEvent.size());

// Get all tasks, make sure firstTask is in there
when().get(TASKS_RESOURCE).then().body(SUBJECT_FIELD, hasItems(savedTask.getSubject()));

// Delete a task that was attached to the event
when().delete(TASK_RESOURCE, savedTask.getId()).then().statusCode(HttpStatus.SC_OK);

// Get all tasks, make sure firstTask is NOT in there
when().get(TASKS_RESOURCE).then().body(SUBJECT_FIELD, not(hasItems(savedTask.getSubject())));

// Check the event again
tasksForEvent = when().get(EVENT_RESOURCE, savedEvent.getId()).as(Event.class).getTasks();
assertEquals(1, tasksForEvent.size());
}

更新:如果我从 Event 类的 @OneToMany 中删除 fetch = FetchType.EAGER,它就可以工作。仍然很高兴知道为什么。下面是我的新 Event 类。

@Entity
public class Event {

@Id
@GeneratedValue(generator = "hibernate-uuid")
@GenericGenerator(name = "hibernate-uuid", strategy = "uuid2")
@Column(unique = true)
String id;

String subject;

@OneToMany(mappedBy="event", cascade = { CascadeType.ALL })
@JsonIgnoreProperties({"event"})
List<Task> tasks;
}

最佳答案

相关摘录自JPA specification :

3.2.4部分:

The semantics of the flush operation, applied to an entity X are as follows:

  • If X is a managed entity, it is synchronized to the database.
    • For all entities Y referenced by a relationship from X, if the relationship to Y has been annotated with the cascade element value cascade=PERSIST or cascade=ALL, the persist operation is applied to Y

3.2.2部分:

The semantics of the persist operation, applied to an entity X are as follows:

  • If X is a removed entity, it becomes managed.

那么,你的情况是怎样的:

  1. 您删除了一个任务
  2. 在事务结束时,Hibernate 将持久化上下文与数据库同步。
  3. 它找到Event 实例。它没有变化,但 PERSIST 操作级联到 tasks
  4. PERSIST 应用于 tasks 集合中的所有 Task,包括已删除的,它再次被管理。

要验证这一点,请为 org.hibernate 包启用 TRACE 日志级别,并搜索包含 un-scheduling entity deletion 的消息。

如果延迟加载任务,则不会将PERSIST应用于它们(当然,如果同时未初始化集合);这就是为什么在这种情况下您看不到这种行为的原因。

解决方案是从 Eventtasks 集合中删除已删除的任务,这样 PERSIST 就不会应用于它。

关于java - Spring 启动 hibernate : cannot delete child object separately,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33409972/

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