如何修复"Detached entity passed to persist" Springboot+Hibernate



伙计们,我尝试了这里或其他网站中提出的不同方法来修复这个错误,我以前也修复过,但在另一种情况下,但这个似乎很复杂,一个名为department的实体,该实体本身具有oneToMany关系,因此该部门可以有一个或多个子部门,并且一个部门应该有一个且只有一个上级部门。

部门实体:

@Entity
@Table(name = "DEPARTMENTS")
public class Department {
@Id
@Column(name = "dep_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private long depId;
private String depName;
@ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "supDep", referencedColumnName = "dep_Id")
@JsonIgnoreProperties(value ={"departments","users"} , allowSetters = true)
private Department supDep;
@OneToMany(mappedBy = "supDep", orphanRemoval = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnoreProperties(value ={"supDep","users"} , allowSetters = true)
private List<Department> departments = new ArrayList<>() ;
Constructors & getters &setters...
}

部门存储库:

@Repository
public interface DepartmentRepository extends JpaRepository<Department,Long> {
Department findByDepName(String name);
}

部门服务接口:

public interface DepartmentService {
Department add(Department department);
Department update(Department department, Long id);
void delete(long id);
List<Department> findAll();
Department findByName(String name);
Department findById(Long id);
User getChefDep(Long idDep);
}

部门服务实施:

@Service(value = "departmentService")
public class DepartmentServiceImpl implements DepartmentService {
....
@Override
public Department add(Department department) {
Department newDep = new Department();
if(department.getDepId() != 0)
newDep.setDepId(department.getDepId());
newDep.setDepName(department.getDepName());
newDep.setChefDep(department.getChefDep());
newDep.setSupDep(department.getSupDep());
newDep.setDepartments(department.getDepartments());
newDep.setUsers(department.getUsers());
return departmentRepository.save(department);
}
...

}

部门控制员ADD方法:

@RestController
@CrossOrigin("*") 
@RequestMapping("/department/")
public class DepartmentController {
...
@PostMapping("add")
public Department add(@RequestBody Department department) { 
return departmentService.add(department);
}
...
}

不管怎样,当我添加一个带有poster的新部门时,它可以工作,并且该部门保存在DATABASE:中

{
"depName": "marketing",
"supDep": null,
"departments": []
}

当我用数据库中不存在的supDep添加一个新部门时,它也能工作,并且这两个实体都保存在DATABASE:中

{
"depName": "Security",
"supDep":
{
"depName": "IT",
"supDep": null,
"departments": [],
"chefDep": 0,
}
}

但是当我添加一个新的部门通过supDep时,一个确实存在的部门:

{
"depName": "sub-marketing",
"supDep":
{
"depId": 1,
"depName": "marketing"
}
}

它抛出了一个恼人的错误:

{
"timestamp": "2020-03-17T14:49:40.071+0000",
"status": 500,
"error": "Internal Server Error",
"message": "detached entity passed to persist: com.ats.remotetimemanager.Model.Department; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.ats.remotetimemanager.Model.Department",
"trace": "org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.ats.remotetimemanager.Model.Department; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.ats.remotetimemanager.Model.Departmentrntat org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:319)rntat org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)rntat org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)rntat org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)rntat org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)rntat org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)rntat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)rntat org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178)

实现方法的正确方法

@Override
public Department add(Department department) {
Department newDep;
if(department.getDepId() != 0) {
Optional<Department> optional = departmentRepository.findById(id);
if(optional.isPresent()) {
newDep = optional.get();
} else {
newDep = new Department();
}
} else {
newDep = new Department();
}
newDep.setDepName(department.getDepName());
newDep.setChefDep(department.getChefDep());
newDep.setSupDep(department.getSupDep());
newDep.setDepartments(department.getDepartments());
newDep.setUsers(department.getUsers());
return departmentRepository.save(department);

}

getters&setters:

public long getDepId() {
return depId;
}
public void setDepId(long depId) {
this.depId = depId;
}
public String getDepName() {
return depName;
}
public void setDepName(String depName) {
this.depName = depName;
}
public Department getSupDep() {
return supDep;
}
public void setSupDep(Department supDep) {
this.supDep = supDep;
}
public List<Department> getDepartments() {
return departments;
}
public void setDepartments(List<Department> departments) {
this.departments = departments;
}
public long getChefDep() {
return chefDep;
}
public void setChefDep(long chefDep) {
this.chefDep = chefDep;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
@Override
public String toString() {
return "Department{" +
"depId=" + depId +
", depName='" + depName + ''' +
", supDep=" + supDep +
", departments=" + departments +
", chefDep=" + chefDep +
'}';
}
}

相关内容

最新更新