【问题标题】:Join 3 tables Hibernate & JPA加入 3 个表 Hibernate 和 JPA
【发布时间】:2016-12-20 10:33:51
【问题描述】:

我有三张桌子,我想加入它们,这让我发疯。

标签:任务 项目 用户

它们之间都有多对多关系:比如项目有多个用户,反之亦然,任务也有多个用户,反之亦然,项目和用户也是如此。 p>

我正在尝试找到一种在 JPA 和 Hibernate 中实现它的方法,我有 2 个选择: ** 1 ** 像这样加入 3 个实体:

项目

   @ManyToMany(fetch = FetchType.EAGER, 
    cascade =
    {
            CascadeType.DETACH,
            CascadeType.MERGE,
            CascadeType.REFRESH,
            CascadeType.PERSIST
    },
    targetEntity = User.class)
  @JoinTable(name = "Collaborators", 
           joinColumns = @JoinColumn(name = "ProjectFk", referencedColumnName = "id", updatable=false, nullable=false), 
           inverseJoinColumns = @JoinColumn(name = "UserFk", referencedColumnName = "id", updatable=false, nullable=false))
  private Set<User> users = new HashSet<>();

用户

    @ManyToMany(fetch = FetchType.EAGER, 
            cascade =
                {
                        CascadeType.DETACH,
                        CascadeType.MERGE,
                        CascadeType.REFRESH,
                        CascadeType.PERSIST
                },
                targetEntity = Project.class)
    @JoinTable(name = "Collaborators", 
           joinColumns = @JoinColumn(name = "UserFk", referencedColumnName = "id", updatable=false, nullable=false), 
           inverseJoinColumns = @JoinColumn(name = "ProjectFk", referencedColumnName = "id", updatable=false, nullable=false))
    private Set<Project> projects = new HashSet<>();

任务

    @ManyToMany(fetch = FetchType.EAGER, 
        cascade =
        {
                CascadeType.DETACH,
                CascadeType.MERGE,
                CascadeType.REFRESH,
                CascadeType.PERSIST
        },
        targetEntity = User.class)
    @JoinTable(name = "Collaborators", 
       joinColumns = @JoinColumn(name = "TaskFk", referencedColumnName = "id", updatable=false, nullable=false), 
       inverseJoinColumns = @JoinColumn(name = "ProjectFk", referencedColumnName = "id", updatable=false, nullable=false))
    @MapKeyJoinColumn(name = "User_id")
    @ElementCollection
    private Map<Project, User> projectUserMap = new HashMap<>();

但这里似乎不起作用

2:创建第 4 个实体并将其命名为 Collaborator,然后尝试找到实现此 SQL 查询的方法:

select * from (
select user.id, Project.id, Task.id
inner join Project on user.join_key = Project.join_key
inner join  Task  on task.join_key = = Project.join_key
) collaborator

任何帮助都会非常感激。谢谢。

【问题讨论】:

  • 我只是查看了您的配置,发现了很多错误和冗余。请研究有关 JPA 集合映射的更多信息以深入了解。
  • 那是因为我不明白如何加入这三个表。我最初使用项目和用户确实很容易成功,但使用三元关联有点困难。
  • 我不使用 mappedBy,因为我想控制删除操作的发生方式。:这是你正在做的一个大错误。 mappedBy 和 coltrolling 删除与 eash other 没有任何关系。在双向关联中,一侧必须是相反的一侧,因此使用 mappedBy。您在 Task 中添加也没有多大意义。如果您有 3 个 ManyToMany 关联,则需要 3 个不同的连接表。
  • 感谢 mappedBy 说明。但这就是我要逃避的。我不想制作三个连接表。我想我会制作 1 个连接表,其中包含 3 个表的 IDs,例如:1_Project / 1_Task / 1_U​​SER 如上一个 SQL 查询 中所示。
  • 如果表有三列,则不是两个实体之间的连接表,需要将其映射为实体。

标签: sql spring hibernate jpa spring-data


【解决方案1】:

应该像下面这样实现:

项目类

 @Entity
public class Project extends ABaseEntity{

private Set<User> users = new HashSet<>();

@ManyToMany
@JoinTable(name = "Collaborators",
        joinColumns = @JoinColumn(name = "Project_ID", referencedColumnName = "id", updatable=false, nullable=false),
        inverseJoinColumns = @JoinColumn(name = "User_ID", referencedColumnName = "id", updatable=false, nullable=false))
public Set<User> getUsers() {
    return users;
}

public void setUsers(Set<User> users) {
    this.users = users;
}
}

用户类

@Entity
@Table(name = "EMA_USER")
public class User extends ABaseEntity {

private Set<Project> projects = new HashSet<>();


@ManyToMany(fetch = FetchType.EAGER,
        cascade = CascadeType.ALL,
        targetEntity = Project.class)
@JoinTable(name = "Collaborators",
        joinColumns = @JoinColumn(name = "User_ID", referencedColumnName = "id", updatable = false, nullable = false),
        inverseJoinColumns = @JoinColumn(name = "Project_ID", referencedColumnName = "id", updatable = false, nullable = false))
public Set<Project> getProjects() {
    return projects;
}

public void setProjects(Set<Project> projects) {
    this.projects = projects;
}
}

任务类

@Entity
public class Task extends ABaseEntity{

private Map<Project, User> projectUserMap = new HashMap<>();

@ManyToMany(
        fetch = FetchType.EAGER,
        cascade = CascadeType.ALL
)
@JoinTable(
        name = "Collaborators",
        joinColumns = @JoinColumn(name = "Task_ID", referencedColumnName = "id", updatable = false, nullable = false),
        inverseJoinColumns = @JoinColumn(name = "User_ID", referencedColumnName = "id", updatable = false, nullable = false)
)
@MapKeyJoinColumn(name = "Project_Id")
public Map<Project, User> getProjectUserMap() {
    return projectUserMap;
}

public void setProjectUserMap(Map<Project, User> projectUserMap) {
    this.projectUserMap = projectUserMap;
}
}

您的任务类有什么问题:

@MapKeyJoinColumn(name = "User_id")

@MapKeyJoinColumn 用于映射 key 的列,这里是 Project 实体。

@ElementCollection

如果映射的值为@Embeddable,则使用

@JoinTable

定义实体类与Map的值中定义的实体之间的关系(这里是Task和User之间的关系)。

 targetEntity = User.class

所有 targetEntity 都是多余的,因为您使用了具有已定义泛型类型的集合。

此外,您不必像这样配置 3 个类。据我了解,您只需要一个包含这三个类之间关系的表。 所以只需像这样定义一个名为 Collaboration 的实体:

@Entity
public class Collaboration{
  @ManyToOne
  private User user;
  @ManyToOne
  private Task task;
  @ManyToOne
  private Project project;
}

通过分离的协作实体,您可以找到所有已给用户的协作。

如果没有这个实体,您可以编写一个查询来查找与给定用户相关的所有任务,然后当然可以自己在 java 代码中收集项目和任务。 查询将像

 'Select t from Task t join projectUserMap m where m = :user '

【讨论】:

  • 感谢您的回复。我不知道谁对你投了反对票,但不是我!如果您愿意在这里解释一下,这三个表是链接的??我的意思是,如果我在该表上调用 collaboration 查询以获取 给定用户任务项目,我将得到它们?
  • 好的。我只关心我是否可以帮助您理解。非经验用户的反对票对我来说不是问题。请在这里询问是否出现问题。我更新了关于您的问题的答案。
  • 如果我的回答符合您的要求,请标记为正确,因为以后可能会有其他人有同样的问题
  • 没错。我只是在实现它,会看到的。谢谢
  • @thanhngo 这个查询没有项目和用户,它只给用户。我们如何使用 JPQL 查询同时找到 Key 和 Value?
猜你喜欢
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多