2013-04-11 18 views
12

Imagine aşağıdaki modeller:Spring JPA'da var olan varlığa işaret eden yeni bir varlık nasıl kaydedilir?

Çalışan:

@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>(); 

Proje: Şimdi

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

Ben varolan projeye başvuruda bulunan yeni bir çalışan oluşturun ve bu çalışanın devam denerseniz, ben Bir hata iletisi:

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 
} 

ve böyle mevcut olanları güncellemek: yee şöyle

public void updateEmployee(EmployeeDTO empDTO) { 

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

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

cevap

19

Sana uygun işlem sınırlarını genişleterek olmadan depo etkileşime giriyor sanırım. Varsayılan olarak, işlem (ve dolayısıyla oturum) sınırı, depo yöntemi düzeyinde bulunur. Bu, Project örneğinin EntityManager'dan ayrılmasına neden olur, böylece kalıcı bir çalışmaya dahil edilemez.

@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)); 
    } 
} 

Bu yaklaşım Project örneği yönetilen bir varlık kalmak neden olur ve böylece operasyon taze Employee örneği doğru kullanıldığını için yürütülecek inat:

burada çözüm müşteriye işlem sınırını uzatmaktır .

İki depo etkileşimi arasındaki fark, ikinci durumda, ilk örnekte olduğu gibi tamamen yönetilmeyen örneklerin olduğu, ayrılmış bir örneğinizin (zaten kalıcıdır, bir kimlik kümesine sahiptir) olacağıdır. kimlik seti yok. Id özelliği, havuzun, persist(…) ve merge(…) numaralı aramalar arasında ayrım yapmasına neden olan şeydir. Yani ilk yaklaşım, bir persist(…)'un tetiklenmesine neden olacak, ikincisi merge(…)'a neden olacaktır.

+0

Teşekkürler, bu işe yarıyor, ancak güncelleme yöntemimin neden depolarından projeleri almadan çalıştığını hala bilmek isterim (ayrıntılar için güncellenmiş soruma bakın) – wannabeartist

+1

Buradaki soruları geçersiz kılmak için iyi bir fikir değil. bir dereceye kadar cevap ver. Yeni sorular sorsan iyi olur. Cevabımı buna göre güncelleyeceğim. –

+0

Bu yayın '@ Transactional' veya JPA'lar mı, yoksa önemli mi? – CorayThan