2016-04-21 76 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方法返回以返回整個層次結構。 –