2016-04-21 59 views
0

我很难尝试将最佳数据库设计(使用BCNF)映射到JPA实体。JPA - 使用弹簧数据在连接表上映射3个表的连接

我有3个实体:地点,人员和行动。
在给定的地方,你有人在执行动作,我们也有他们在那里执行动作的次数。

请注意,每个实体可以独立存在:您可以拥有一个没有执行任何动作的地方,一个没有执行任何动作和动作的人不会被任何人执行。

为了存储这些信息,我模仿数据库模式,因为这:

DB design

现在我试图创建JPA实体映射这一点,这就是我有问题。
我想遍历从地方开始的对象,从获取的地方遍历所有执行其中的动作的人,最后让每个人都能够看到他们在那个地方执行了哪些动作以及他们做了多少次。

从纯SQL角度来看,这是很容易:

取人对那个地方名单:

  • 选择不同(pe.name)距离Place PL,人PE,AP的actionPerformed其中AP .place_id = pl.id和ap.person_id = pe.id和pl.id = < 地方ID>

然后,对于每个人返回:

  • 从地点pl,人员pe,操作a,ActionPerformed ap选择a.name,ap.count其中ap.place_id = pl.id和ap.person_id = pe.id和ap.action_id = a.id和pl.id = < 地方ID>和pe.id = < 人ID>

我想用那种深入行为映射在JPA实体:

  • 拥有Place的实体,并拥有执行的人员列表在它的人实体
  • d行为,有在那个地方

各自的计数操作的列表是一些可能用JPA怎么办?或者我在想错误的方式?

这是我在实体上的尝试:

与地方开始,参考人:

public class Place implements Serializable { 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private Integer id; 

    private String name; 

    @ManyToMany(fetch=FetchType.EAGER) 
    @JoinTable(
     name="ActionPerformed" 
     , joinColumns={ 
      @JoinColumn(name="place_id", nullable=false) 
      } 
     , inverseJoinColumns={ 
      @JoinColumn(name="person_id", nullable=false) 
      } 
     ) 
    private List<Person> people; 

    <getters, setters, etc...> 
} 

于是人们,参照执行的操作(用计数):

public class Person implements Serializable { 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private Integer id; 

    private String name; 

    @OneToMany(mappedBy="person", fetch=FetchType.EAGER) 
    private List<ActionPerformed> actionsPerformed; 

    <getters, setters, etc...> 
} 

的行动,主要用于他们的名字:

public class Action implements Serializable { 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private Integer id; 

    private String name; 

    <getters, setters, etc...> 
} 

和连接表,PK对象向他们之间的关联:

@Entity 
public class ActionPerformed implements Serializable { 
    @EmbeddedId 
    private ActionPerformedPK pk; 

    @Column(nullable=false) 
    private Integer count; 

    @ManyToOne 
    @JoinColumn(name="place_id") 
    private Place place; 

    @ManyToOne 
    @JoinColumn(name="person_id") 
    private Person person; 

    @ManyToOne 
    @JoinColumn(name="action_id") 
    private Action action; 

    <getters, setters, etc...> 
} 

@Embeddable 
public class ActionPerformedPK implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Column(name="place_id") 
    private Integer placeId; 

    @Column(name="person_id") 
    private Integer personId; 

    @Column(name="action_id") 
    private Integer actionId; 

    <getters, setters, etc...> 
} 

的一个问题,我看到的是,当我查询的地方,我得到多个条目的每个人执行的动作有 - 每一个进入连接表。 此外,当检查每个人列出的动作时,我会得到该人在每个地方执行的所有动作(它不考虑发起查询的地点)。

有没有办法在JPA映射或实体设计中解决这个问题?或者我将不得不改变数据库设计?

P.S .:我检查了至少一打类似于这个问题的帖子,但没有一个与我尝试的设计完全匹配,所以提出的解决方案不适用于我的情况。 P.S.2:我使用Spring Data和CrudRepositories从实体创建存储库。

P.S.3:对不起,语法错误或“怪异”的句子,英语不是我的母语。

在此先感谢!

回答

0

我还没有逐行检查过你的代码,因为我认为你的问题没有被数据库设计和类注解回答,而是被查询回答。

如果要通过比尔在伦敦完成了所有的动作表演,就喜欢写东西

select ap from ActionPerformance ap where ap.person.name = "Bill" and ap.place.name = "London" 

和JPQL将生成类似于您从描述了一些SQL。

+0

谭谭,感谢您的评论!但是,我在寻找的是使用Spring Data自动生成的存储库浏览实体的一种方法。因此,通过为JPA创建接口,我希望能够浏览对象。最终,Place对象甚至可以直接从REST api GET方法返回以返回整个层次结构。 –