【问题标题】:ManyToMany relation and save objects多对多关系和保存对象
【发布时间】:2018-11-16 07:11:50
【问题描述】:

我在两个实体之间存在多对多关系:teamperson。我创建了一种将人员添加到团队的方法。

如果我只在一个服务(团队)中创建此方法,如果我有 manyToMany 关系,我是否可以将人员添加到团队和团队到人员,或者我是否需要在人员服务中创建相同的方法?

这是我的方法:

public void addPersonsToTeams(Long teamId, Long personId) {
        Assert.notNull(personId, "Object can't be null!");
        Assert.notNull(teamId, "Object can't be null!");
        try {
            Person person = personRepository.getOne(personId);
            Team team = teamRepository.getOne(teamId);
            person.getTeams().add(team);
            personRepository.save(person);
        } catch (Exception e) {
            throw new CreateEntityException();
        }

    }

【问题讨论】:

  • 你是在问这是否会正确地将数据保存到数据库中?另外,请为您正在使用的框架添加其他相关标签,如 jpa、hibernate 等。
  • 两个站点都支持。所以我不需要在个人服务中创建那种方法?
  • 假设您有一个连接表,这应该正确地向该连接表插入一个新条目,我认为这应该是您所需要的。但是,与往常一样,最好的确保方法是实际(测试)运行它。
  • 是的,我知道,但是要运行它,我需要 res cotroller 方法(我认为是 POST),但我不知道如何编写这种方法:/
  • 如果运行成功,那就好了。如果它失败了,我们可以帮助您修复它。但是,如果您无法运行它,那么我们无能为力。对不起。

标签: java spring rest spring-data-jpa h2


【解决方案1】:

编辑 来自https://stackoverflow.com/users/2224047/nikolay-shevchenko 的评论我了解到ORM 框架可以自行解决多对多同步问题。我也认为它可以管理相关的锁定问题。无论如何我都会让我之前的答案,因为我认为这仍然是一个很好的设计问题。

首先,如果一个对象具有不同的生命周期,则应避免将它们包含到另一个对象中。您应该简单地通过 Id 引用另一个对象。你应该看看aggregate 的概念。现在我不知道您使用的底层 ORM 将如何管理它。

具体来说,这是错误的 imo

Team team = teamRepository.getOne(teamId);
person.getTeams().add(team);
personRepository.save(person);

因为(至少在代码中)您似乎将团队对象的副本存储在存储库中的人员内部。但是可以在此上下文之外修改团队对象。例如,团队可以有一个新人。然后,您的人员对象将包含一个与团队存储库中存储的对象不同步的团队对象。您最终会得到 2 个不同的团队对象存储在不同的位置。现在再次,如果您的 ORM 框架为您解决了这个问题,那么您可能很好,但我认为您仍然应该考虑重新设计您的代码,并避免让您的 ORM 解决这种困境。

我会编写类似的代码

if(teamRepository.contains(teamId)){
    person.getTeamIds().add(teamId);
    personRepository.save(person);
}

现在要让团队对象也同步,您可以使用某种领域事件。在团队服务中收听,在团队服务中做相反的操作。但是如果这个同步操作是在不同的事务中完成的,那么这意味着在某些时候你的数据库是不一致的。这对您来说可能是个问题,也可能不是。如果您的后端在同步操作等之间崩溃,也会发生什么......

所以我认为你应该挑战你的设计以及团队和个人服务是分开的这一事实。也许它们是同一服务的一部分,甚至是聚合的,然后您可以同时更新它们?

这是一个庞大的设计问题,我建议看看什么是聚合并阅读domain driven design

希望这会有所帮助:)

【讨论】:

  • Because you are storing a copy of the team object inside a person in your repository。多对多关系通常使用带有 2 个 FK 的联合表,因此没有“对象副本”。如果同一类的两个托管实例的 ID 相等,则 Hibernate 认为它们是相同的实例。所以你的例子是非 ORM 风格
  • 确实我不知道hibernate会如何做到这一点,我会改写。尽管如此,IMO 认为 hibernate 会为您解决设计问题是一种不好的做法。
猜你喜欢
  • 2012-01-03
  • 1970-01-01
  • 1970-01-01
  • 2017-01-22
  • 2015-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多