在Spring Boot Jpa中相互连接三个实体时出现问题

时间:2018-12-11 22:58:09

标签: java spring spring-data-jpa

假设我的数据库中有一个表project。每个project有很多users,每个user可能有很多projects。这将是经典的ManyToMany相关性,因此,如果我想在Spring Boot JPA中对此进行描述,则可以执行以下操作:

设置我的实体并进行连接:

@Entity
public class User {
  @id
  @Column(name="ID")  
  public int id;

  @ManyToMany
  public Set<Project> projectSet;
}

@Entity
@Table(name="PROJECT")
public class Project {
  @id
  @Column("ID")
  private int id;

  @ManyToMany
  private Set<User> users;
}

实施我的存储库:

@Repository
public interface ProjectRepo implements JpaRepository<Project, Integer> {
  public Set<User> getAllUsers();
}

现在让我们假设我想指定每个用户在该项目中所扮演的角色。因此,我将有一个表role,该表使用以下实体表示指定不同的角色:

@Entity
@Table(name="ROLES")
public class Role {
  @id
  @Column(name="ID")
  private int id;

  @Column(name="DESCRIPTION")
  private String description;
}

但是该如何连接到我的用户和项目?因此,我想展示的是,一个用户可以在一个项目中拥有一个角色,但是在许多项目中可以具有多个角色。同样,一个角色可以分配给一个或多个项目中的许多用户,并且一个项目可以具有许多用户,其中每个用户只有一个角色,但是那里有许多角色。如果仅将@ManyToMany Set<Roles> roleSet添加到Users中,就无法确定哪个用户在哪个项目中具有哪个角色。那么如何描绘呢?我需要创建第三类来连接它们吗?

编辑1:

为了让我澄清,我将尝试在marknote的答案中提供建议的代码-

让我们假设我有上面的类(ProjectUserRole),我想描述每个用户在一个项目中都有特定的角色,但是可能有另一个角色在另一个项目中的角色。另外,在一个项目中不能同时扮演多个角色(为了简单起见)。

因此,我将创建一个新类Assignment(非常类似于我将在数据库结构中解决该用例的问题),并将其与我的User,我的Project和我的Role

@Entity
@Table(name="USER")
public class User {
  @id
  @Column(name="id")
  private int id;

  @Column(name="firstname")
  private String firstname;

  @Column(name="lastname")
  private String lastname;

  @OneToMany
  private List<Assignment> assignments;
  //getters and setters and stuff
}

@Entity
@Table(name="PROJECT")
public class Project {
  @id
  @Column(name="PNUM")
  private String pnum;

  @Column(name="PNAME")
  private String pname;

  @OneToMany
  private List<Assignment> assignments;
  //getters and setters and stuff
}

@Entity
@Table(name="ROLE")
public class Role {
  @id
  @Column(name="id")
  private int id;

  @Column(name="DESCRIPTION")
  private String description;

  @OneToMany
  private List<Assignment> assignments;
  //getters and setters and stuff
}

到目前为止还可以,所以我将创建以下Assignment类。我需要能够从UserProject以及Role进行跟踪,因此我需要三个字段。让我们想象一下(通常)用例:表Assignment通过将FK中的PK组合到名称表来连接UserProjectRole。现在,据我所知,通常在Spring Boot JPA中使用@Embeddable注释的新类中提供了组合PK。从这个角度来看,我将执行以下操作:

@Embeddable
public class AssignmentId implements Serializable {
  private User user;
  private Project project;
  private Role role;
}

并将我的Assignment类更改为:

@Entity
@Table(name="ASSIGNMENT")
public class Assignment {
  @EmbeddedId
  private AssignmentId assignmentId;
}

现在这样做时,在尝试运行spring-boot时遇到以下错误:

  

org.springframework.beans.factory.BeanCreationException:在类路径资源[org / springframework / boot / autoconfigure / orm / jpa / HibernateJpaConfiguration.class]中创建名称为'entityManagerFactory'的bean时出错:调用init方法失败;嵌套的异常是javax.persistence.PersistenceException:[PersistenceUnit:默认]无法构建Hibernate SessionFactory。嵌套的异常是org.hibernate.MappingException:无法确定com.demo.example.entity.Project的类型,在表:分配处,对于列:[org.hibernate.mapping.Column(project)]

有人可以与此错误相关吗?我认为@EmbeddedId可能有问题。

编辑2

问题出在@Embedded类上。将Entity连接到元素时出现问题:

private Role role;
private Project project;
private User user;

1 个答案:

答案 0 :(得分:3)

取决于您的业务需求。 假设用户的角色在项目中会有所不同,您可以引入另一个类Assignment,然后将其变为3 @OneToMany :) enter image description here

您将使用User来引用Project中的RoleAssignment@ManyToOne,但是您可能需要也可能不需要使用{{1} }。关于实现@OneToMany的最佳实践的非常好的文章:https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate感谢@ vlad-mihalcea