복붙노트

[SPRING] Spring JPA의 기존 엔티티를 참조하는 새로운 엔티티를 저장하는 방법은 무엇입니까?

SPRING

Spring JPA의 기존 엔티티를 참조하는 새로운 엔티티를 저장하는 방법은 무엇입니까?

다음 모델을 상상해보십시오.

종업원:

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "employee_project", joinColumns = @JoinColumn(name = "Emp_Id"), inverseJoinColumns = @JoinColumn(name = "Proj_id"))
private Set<Project> projects = new HashSet<Project>();

계획:

@ManyToMany(mappedBy = "projects")
private Set<Employee> employees = new HashSet<Employee>();

이제 기존 프로젝트를 참조하는 새 직원을 만들고 해당 직원을 유지하려고하면 오류가 발생합니다.

detached entity passed to persist: Project

다음과 같이 직원을 만듭니다.

public void createNewEmployee(EmployeeDTO empDTO) {

  Employee emp = new Employee();
  // add stuff from DTO, including projects

  repository.saveAndFlush(emp);  // FAILS
}

나는 다음과 같이 기존의 것들을 업데이트한다.

public void updateEmployee(EmployeeDTO empDTO) {

   Employee emp = repository.findOne(empDTO.getId());
   // set stuff from DTO, including projects

   repository.saveAndFlush(emp);  // WORKS!
}

해결법

  1. ==============================

    1.트랜잭션 경계를 적절하게 확장하지 않고 저장소와 상호 작용하는 것 같습니다. 기본적으로 트랜잭션 (및 세션) 경계는 저장소 메서드 수준에 있습니다. 이로 인해 Project 인스턴스가 EntityManager에서 분리되어 지속 작업에 포함될 수 없습니다.

    트랜잭션 경계를 적절하게 확장하지 않고 저장소와 상호 작용하는 것 같습니다. 기본적으로 트랜잭션 (및 세션) 경계는 저장소 메서드 수준에 있습니다. 이로 인해 Project 인스턴스가 EntityManager에서 분리되어 지속 작업에 포함될 수 없습니다.

    여기서의 해결책은 트랜잭션 경계를 클라이언트로 확장하는 것입니다.

    @Component
    class YourRepositoryClient {
    
      private final ProjectRepository projects;
      private final EmployeeRepository employees;
    
      // … constructor for autowiring
    
      @Transactional
      public void doSomething() {
        Project project = projects.findOne(1L);
        Employee employee = employees.save(new Employee(project));
      }
    }
    

    이 접근법은 Project 인스턴스가 관리되는 엔티티를 유지하도록하므로 새로운 Employee 인스턴스가 올바르게 처리되도록 지속 작업이 실행됩니다.

    두 개의 저장소 상호 작용과의 차이점은 두 번째 경우에는 분리 된 인스턴스 (이미 보존되어 있고 id 세트가 있음)가있는 것입니다. 첫 번째 예와 같이 ID가없는 완전히 관리되지 않는 인스턴스가있는 경우 세트. id 속성은 저장소가 persist (...) 및 merge (...) 호출을 구별하도록하는 역할을합니다. 따라서 첫 번째 방법은 지속 (...)을 유발하고 두 번째 방법은 병합 (...)을 유발합니다.

  2. from https://stackoverflow.com/questions/15943783/how-to-save-a-new-entity-that-refers-existing-entity-in-spring-jpa by cc-by-sa and MIT license