JPA: обновить только таблицу сопоставления

У меня есть объекты Project и Employee, которые имеют отношение ManyToMany, как показано ниже.

@Entity
public class Project {
     @Id @GeneratedValue
     private int projectId;

     private String projectName;

     // has some additional columns

     @ManyToMany(mappedBy = "projects")
     private List<Employee> emp = new ArrayList<Employee> ();
     ....
     .....

 }


 @Entity
public class Employee {
     @Id @GeneratedValue
     private int id;
     private String firstName;
     private String lastName;

     @ManyToMany(cascade=CascadeType.ALL)
     List<Project> projects = new ArrayList<Project> ();

     ....
     ....
}

Когда я использую вышеуказанные объекты, JPA создает таблицу mppping «Employee_Project», как показано ниже.

create table Employee_Project (emp_id integer not null, projects_projectId integer not null)

Мой вопрос: всякий раз, когда добавляется новый сотрудник, я хочу обновить только таблицу сотрудников и таблицу сопоставления Employee_Project, предположим, что я знаю идентификатор проекта, с которым я хотел бы сопоставить этого сотрудника. (не касаясь таблицы/сущности проекта, я имею в виду, почему я должен предоставлять полный объект проекта, сохраняя при этом только сущность сотрудника, как я могу сделать это через jpa?)


person Hari Krishna    schedule 27.01.2020    source источник


Ответы (1)


Вам не нужно предоставлять весь объект Project. Используйте EntityManager.getReference(projectId) или JpaRepository.getOne(projectId).

Эти методы создадут прокси-объект с соответствующим идентификатором, а не загрузят весь объект Project из хранилища данных.

РЕДАКТИРОВАТЬ Ваш метод обслуживания должен выглядеть примерно так:

@Transactional
public void createEmployee(Employee employee, Long projectId) {
    employee.setProjects(List.of(projectRepository.getOne(projectId));
    employeeRepository.save(employee);
}

В качестве примечания, CascadeType.ALL (в частности, потому что оно включает CascadeType.MERGE и CascadeType.REMOVE) не имеет смысла для @ManyToMany. Если вы не планируете создать Project, создав Employee, CascadeType.PERSIST тоже не имеет смысла.

person crizzis    schedule 27.01.2020
comment
Я использовал метод EntityManager.getReference для получения прокси-объекта проекта и прикрепил его к новому объекту сотрудника. Когда я пытаюсь сохранить этот новый объект Employee, я получаю сообщение об ошибке, например, org.hibernate.PersistentObjectException: неинициализированный прокси-сервер передается в persist() - person Hari Krishna; 27.01.2020
comment
У вас есть транзакция вокруг вашего метода обслуживания, верно? - person crizzis; 28.01.2020
comment
Криззис, мой вопрос о другом. Я спрашиваю, могу ли я обновить таблицу объектов (Сотрудник) и сопоставление (Employee_Project_mapping)) отдельно вместо обновления другой таблицы объектов (Проект), когда новый сотрудник подключается и сопоставляется с каким-либо существующим проектом. - person Hari Krishna; 30.01.2020
comment
Да, я это прекрасно понимаю. У вас есть транзакция вокруг вашего метода обслуживания? У вас должен быть один, иначе решение вам не подойдет - person crizzis; 30.01.2020