wan*_*ist 13 java spring jpa spring-data spring-data-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>();
Run Code Online (Sandbox Code Playgroud)
项目:
@ManyToMany(mappedBy = "projects")
private Set<Employee> employees = new HashSet<Employee>();
Run Code Online (Sandbox Code Playgroud)
现在,如果我创建一个引用现有项目并尝试保留该员工的新员工,则会收到错误消息:
detached entity passed to persist: Project
Run Code Online (Sandbox Code Playgroud)
我按如下方式创建员工:
public void createNewEmployee(EmployeeDTO empDTO) {
Employee emp = new Employee();
// add stuff from DTO, including projects
repository.saveAndFlush(emp); // FAILS
}
Run Code Online (Sandbox Code Playgroud)
我更新现有的这样的:
public void updateEmployee(EmployeeDTO empDTO) {
Employee emp = repository.findOne(empDTO.getId());
// set stuff from DTO, including projects
repository.saveAndFlush(emp); // WORKS!
}
Run Code Online (Sandbox Code Playgroud)
Oli*_*ohm 20
我猜你正在与存储库进行交互而不适当地扩展事务边界.默认情况下,事务(以及会话)边界位于存储库方法级别.这会导致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));
}
}
Run Code Online (Sandbox Code Playgroud)
此方法使Project实例保持为管理实体,从而执行持久操作以Employee正确处理新实例.
与两个存储库交互的区别在于,在第二种情况下,您将拥有一个分离的实例(已经被持久化,具有一个id集),在第一个示例中,您拥有一个没有id的完全非托管实例组.id属性是导致存储库区分调用persist(…)和merge(…).所以第一种方法会导致a persist(…)被触发,第二种方法会导致a merge(…).
| 归档时间: |
|
| 查看次数: |
13174 次 |
| 最近记录: |