Java 保存时禁用多通关系JPA中的级联
在数据库中保存实体时出现问题 我有一些类似(非常简单的):Java 保存时禁用多通关系JPA中的级联,java,jpa,eclipselink,cascade,many-to-one,Java,Jpa,Eclipselink,Cascade,Many To One,在数据库中保存实体时出现问题 我有一些类似(非常简单的): 加载员工-实体时,您还可以加载建筑-实体(取决于您的JPA提供商和版本,默认为fetchtype Earge还是LAZY),加载建筑-实体时,您还将加载连接到该实体的所有员工 这意味着加载一个员工-实体将/可能加载连接到同一建筑的所有员工,从而为所有这些实体运行@PostLoad-方法。当这发生在事务内部时,我会假设在事务提交时,@PostLoad-方法所做的更改会被持久化。只是扩展了Tobb的回答: 发生这种情况是因为您正在使用合并调
加载
员工
-实体时,您还可以加载建筑
-实体(取决于您的JPA提供商和版本,默认为fetchtype Earge还是LAZY),加载建筑
-实体时,您还将加载连接到该实体的所有员工
这意味着加载一个员工
-实体将/可能加载连接到同一建筑
的所有员工
,从而为所有这些实体运行@PostLoad
-方法。当这发生在事务内部时,我会假设在事务提交时,@PostLoad
-方法所做的更改会被持久化。只是扩展了Tobb的回答:
发生这种情况是因为您正在使用合并调用加载员工。该实体与建筑有1:1的关系,默认情况下,该建筑会被急切地抓取,从而迫使建筑也被加载
然后,建筑也有一个1:M到Employees,您已经用fetch=FetchType.EAGER标记了它,强制所有员工也被加载
如果不希望加载所有员工,从而迫使JPA调用他们的postLoad方法,则需要防止加载一个或多个关系。选项:
将一个或多个标记为fetch=FetchType.LAZY
- 这对于集合来说并不重要,但是使用1:1映射可能需要额外的支持。例如,日食需要编织
从实体中删除一个或多个映射李>
删除更改实体的后加载逻辑。这似乎不是操作实体的最佳地点,因为对实体的任何访问都将强制更新,即使事务中可能没有其他更改。您可能会提出不同的策略,例如一次性批量更新遗留数据,而不是长期影响应用程序的策略。如果必须,可以改用@PreUpdate
如果您选择使用延迟抓取,仍然可以根据需要通过抓取连接、查询提示和/或抓取/加载组逐个查询地覆盖它。您尚未在此处定义任何级联。显示@PostLoad.的代码。您提供的代码中没有任何内容会将一名员工
的更新级联到大楼
或大楼
的另一名员工
的更新。显示您是否“保存”了员工
。是的,我同意您的看法。我添加了如何保存此实体。是否您所处的事务也会修改其他员工
s?请记住,对事务中检索到的对象所做的任何更改都将被持久化,而无需调用merge
-方法。另外,当您说员工被“修改”时,这意味着什么?当我说员工实体被修改时,我指的是从我的员工实体检索建筑时,PostLoad方法所做的更改。我不认为我在一个事务中更改了任何员工,只更改了PostLoad,但我会仔细看一看。问题是同一个事务中的PostLoad。解决方案是删除服务的后加载逻辑。谢谢!
@Entity
public class Building {
@OneToMany(mappedBy = "building", fetch = FetchType.EAGER)
private List<Employee> employees;
}
@Entity
public class Employee {
@NotNull
@ManyToOne
@JoinFetch(INNER)
@JoinColumn
private Building building;
@PostLoad
private void onLoad(){
if (this.plannedOrder == null) {
//For old entities in this DB, update plannedOrder if null
if (this.order < FIRST.getCode()) {
this.plannedOrder = FIRST;
} else if (this.order >= FIRST.getCode() && this.order < SECOND.getCode()) {
this.plannedOrder = SECOND;
} else if (this.order >= DEFAULT.getCode() && this.order < SEC_LAST.getCode()) {
this.plannedOrder = DEFAULT;
} else if (this.order >= SEC_LAST.getCode() && this.order < LAST.getCode()) {
this.plannedOrder = SEC_LAST;
} else if (this.order >= LAST.getCode()) {
this.plannedOrder = LAST;
} else {
this.plannedOrder = DEFAULT;
}
}
}
if (entity.getId() == null) {
entityManager.persist(entity);
return entity;
}
return entityManager.merge(entity);