2017-03-23 32 views
1

我想將關鍵字與我的數據庫中的主體相關聯,並讓它們通過連接表進行鏈接。大部分時間我都不會知道一個關鍵字是否已經在表中,所以如果是這樣,我想讓它忽略,而是將關聯保存到連接表中。我想知道是否可以使用註釋執行這樣的任務。如何將實體保存到一個表和它的連接表中,而不需要將實體作爲它們各自表中的重複項

例如:

我已經subject類聲明爲這樣:

@Entity 
public class Subject{ 

@Id 
private Long Id; 
private String subject; 

@ManyToMany 
@JoinTable 
private List<Keyword> keywords 

public Subject(){ 
    this.keywords = new ArrayList<>(); 
} 

//getters and setters 
} 

keyword分別宣佈

@Entity 
public class Keyword{ 

@Id 
private Long Id; 
private String keyword; 

@ManyToOne(mappedBy="keywords") 
@JoinTable 
private Set<Subject> subject; 

//getters and setters 
} 

我一會兒現在麻煩的是:當我嘗試關聯這些關鍵字到另一個主題我在關鍵字表中獲得一個插入.Same適用於我在下面用示例代碼描述的連接表:

例如:

Subject s = new Subject() 
     s.setSubject("mechanics"); 

List<Keyword> ks = new ArrayList<>(); 
     k.add(new Keyword("inertia"); 
     k.add(new Keyword("momentum"); 

//start em 
em.persist(s); 
for(Keyword k : ks){ 
    k.setSubject(s); 
    em.persist(k); 
     } 
//close em 

上面的代碼結束後,我得到的表,看起來像這樣

KEYWORD   KEYWORD_SUBJECT   SUBJECT 
id keyword  keywordid subjectid id  subject 
1  inertia  1   1   1  mechanics 
2  momentum 2   1 

如果我相同的關鍵字相關聯的另一個主題,做一個合併我得到的表重複如下所示的值。

代碼示例:

Subject s = new Subject() 
      s.setSubject("engineering"); 

List<Keyword> ks = new ArrayList<>(); 
     k.add(new Keyword("inertia"); 
     k.add(new Keyword("momentum"); 

//start em 
em.persist(s); 
for(Keyword k : ks){ 
    k.setSubject(s); 
    em.merge(k); 
     } 
//close em 

上面的代碼結束後,我得到的表看起來像這樣

KEYWORD   KEYWORD_SUBJECT   SUBJECT 
id keyword  keywordid subjectid id  subject 
1  inertia  1   1   1  mechanics 
2  momentum 2   1   2  engineering 
3  inertia  3   2 
4  momentum 4   2 

摘要 什麼,我想要做的

  • 保存邏輯流關鍵字和副主題。
  • 如果關鍵字在表更新連接表中。
  • 如果沒有保存關鍵字並更新連接表。

含修正修訂這裏

+0

爲什麼不張貼您使用的持久對象的代碼?顯示對象的創建,以及它們處於什麼生命週期狀態,以及事務開始/提交 –

+0

@BillyFrost問題updated.will會很高興如果你能幫忙 – Kaizen

回答

0

解決方案基於@JBNizet建議。

創建在SubjectKeyword單向關係如下:

@Entity 
@Table(name = "subjects") 
public class Subjects implements Serializable { 

    private static final long serialVersionUID = 556704632247293531L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "SUBJECT_ID", nullable = false, updatable = false) 
    private Long subjectId; 

    @Basic 
    @Column(name = "SUBJECTS", nullable = false, updatable = true) 
    private String subject; 

    @ManyToMany(cascade =CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = Keyword.class) 
    @JoinTable(name = "subject_keywords") 
    private Set<Keyword> keywords; 
     //getters,setters,hascode and equals 
} 

Keyword類:

@Entity 
@Table(name = "keyword") 
public class Keyword implements Serializable{ 

    private static final long serialVersionUID = 6979246221117236955L; 


    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "keyword_id", nullable = false, updatable = false) 
    private Long keywordId; 

    @Basic 
    @Column(name = "keyword", nullable = false, updatable = true) 
    private String keyword; 
    //getters,setters,hashcode and equals 
} 

的方法,其濾出keywords

public static Set<Keyword> filter(Subject subject, Set<Keyword> keywords) { 

     subjects.getKeywords().forEach((Keyword subjectKeyword) -> { 
      //compare keywords 
      Predicate<Keyword> departmentPredicate = (Keyword k) -> k.getKeyword().equalsIgnoreCase(subjectKeyword.getKeyword()); 
      //remove duplicate keyword 
      keywords.removeIf(departmentPredicate); 
     }); 
     return keywords; 
    } 

最後,新的名單和相關的合併

 Subjects find = em.find(Subjects.class, Long.valueOf(1)); 

     Set<Keyword> filter = filter(find, keyword); 

     //associate it with the subject 
     find.getKeywords().addAll(filter); 

     //save the subject back 
     em.merge(find); 
0

許多問題。

首先,你的映射沒有意義。如果你有一個主題List<Keyword>,它不能是一個ManyToOne。它是OneToMany或ManyToMany,因爲該列表包含...許多關鍵字。其次,如果關鍵字中有Subject,則它不能是OneToMany,因爲只有一個主題。它可以是OneToOne或ManyToOne。

看來,一個關鍵字是在幾個主題,並且一個主題有幾個關鍵字,所以你有什麼是ManyToMany,並且關鍵字的字段應該是Set<Subject>類型(給定的關鍵字存在於幾個主題)。

由於它是雙向關聯,因此它們中的一個必須使用mappedBy = "nameOfTheMatchingFieldInTheOtherEntity"。在ManyToMany上,您可以自由選擇哪一個。

現在,關於你的問題。關鍵字由其ID標識唯一標識。如果您添加了一個沒有任何ID的新關鍵字,Hibernate就不可能知道您想要搜索的關鍵字具有相同的文本,並使用該現有關鍵字而不是新關鍵字。所以你需要編碼:

void addKeywordToSubject(String keywordText, Subject subject) { 
    Keyword keyword = findKeywordByText(keywordText); 
    if (keyword == null) { 
     keyword = new Keyword(keywordText); 
    } 
    subject.addKeyword(keyword); 
} 

雖然。由於併發線程很可能會這樣做,因此除非在數據庫中爲關鍵字文本設置了唯一約束,否則最終可能會出現重複關鍵字。

相關問題