【问题标题】:Spring, add one column to an existing Many to Many list in one querySpring,在一个查询中将一列添加到现有的多对多列表中
【发布时间】:2019-12-18 02:02:01
【问题描述】:

我有一个Project 实体,它具有以下属性:

  @ManyToMany
  @JoinTable(
          name = "employee_projects",
          joinColumns = @JoinColumn(name = "project_id"),
          inverseJoinColumns = @JoinColumn(name = "employee_id")
  )
  private List<Employee> employees;

当我将另一个employee 添加到employees 时,我正在执行以下服务方法。

  Employee addEmployeeToProject(long id, Employee employee) {
    Project project = findByProjectId(id);
    List<Employee> oldEmployees = project.getEmployees();
    oldEmployees.add(employee);
    project.setEmployees(oldEmployees);
    projectRepository.save(project);
    return employee;
  }

效果很好。但后来我实际上开始记录 SQL 请求,这就是实际发生的情况:

2019-12-17 18:45:52.644 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : delete from employee_projects where project_id=?
2019-12-17 18:45:52.646 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.648 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.648 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.650 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.650 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.651 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.651 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.651 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.652 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.652 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.652 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.652 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.653 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.653 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)
2019-12-17 18:45:52.653 DEBUG 14324 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into employee_projects (project_id, employee_id) values (?, ?)

所以他首先删除所有列(从给定项目中删除所有员工)。然后再次添加所有以前的+新的。我想如果我替换整个系列会发生什么。但我只需要插入一个对象,为了节省时间,我可以编写自己的插入查询,这样它只插入我想要插入的一名新员工,而不是删除所有内容并再次添加所有内容。但是除了编写自己的查询之外,还有更好的方法在一个请求/查询中完成吗?

编辑:

如果我使用本机查询,我只能定义 INSERT 查询吗? JPQL 不可以吗?

【问题讨论】:

    标签: java sql spring jpa


    【解决方案1】:

    当然。首先,首先在单个事务中完成所有这些操作,从而受益于对托管实体的修改自动持久化这一事实。无需拨打save()

    然后,了解 Java 将引用传递给对象。如果你得到一个项目的员工集合,你不会得到集合的副本。你得到它的参考。因此,将员工添加到该集合会有效地修改项目员工的集合。无需在项目中重新设置集合。

    所以最后,你只需要

    @Transactional
    public void addEmployeeToProject(long id, Employee employee) {
        Project project = findByProjectId(id);
        project.getEmployees().add(employee);
    }
    

    【讨论】:

    • 是的,在项目中再次设置集合是不必要的,但主要问题是调用save 而不是在一个事务中完成所有操作。谢谢您的帮助。我以前从未真正与@Transactional 合作过。看看我是否也可以在其他一些方法中使用它。
    • 哦,但我只是仔细检查了一遍。它仍然记录我在上面发布的所有查询(仍然删除整个集合,然后在单独的查询中添加每个员工)。它现在不应该能够在一个查询中完成所有操作吗?
    • 是的,应该。但是没有完整的复制代码,很难说为什么没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    相关资源
    最近更新 更多