2014-02-15 91 views
0

我有一個類A可以具有一個關聯到多個B秒(一到多):休眠一個一對多關聯保存重複

@Entity 
@Table(name = "a") 
public class A implements Serializable { 

private static final long serialVersionUID = 6796905221158242611L; 

@Id 
@GeneratedValue 
@Column(name = "a_id") 
private Long a_id; 

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

@OneToMany(mappedBy = "a", cascade = CascadeType.ALL) 
private Set<B> bs; 

public void addB(B b) { 
    if(bs == null) 
    bs = new HashSet<B>(); 

    bs.add(b); 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 
} 

和類B存儲參考到A

@Entity 
@Table(name = "b") 
public class B implements Serializable { 

private static final long serialVersionUID = 6063558165223241323L; 

@Id 
@GeneratedValue 
@Column(name = "b_id") 
private Long b_id; 

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

@ManyToOne(cascade = CascadeType.ALL) 
@JoinColumn(name = "a_id") 
private A a; 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public A getA() { 
    return a; 
} 

public void setA(A a) { 
    this.a = a; 
} 
} 

現在當我執行下面的代碼Hibernate會保存在具有名稱b1b兩個兩個條目。我不知道如何避免這個或我做錯了什麼。

EntityManagerFactory emf = Persistence.createEntityManagerFactory(Configurations.MYSQL); 
EntityManager em = emf.createEntityManager(); 

em.getTransaction().begin(); 

A a1 = new A(); 
a1.setName("a1"); 

A a2 = new A(); 
a2.setName("a2"); 

B b = new B(); 
b.setName("b1"); 

a1.addB(b); 
a2.addB(b); 

em.merge(a1); 
em.merge(a2); 

em.getTransaction().commit(); 
+0

合併A1和A2,然後B,然後將B添加到As中。這實際上應該可行。 – sorencito

回答

0

可以通過發明A和B(其然後由本身具有兩個條目)之間的映射表實現這一點,因爲每個B存儲的參照其A柱,並作爲數據庫的第一範式狀態,你只有原子值,所以在一列中沒有A的兩個主鍵A的單個B行。

1

我想你應該保存a1和a2而不是合併它們。從javadocs,這是合併。

將給定對象的狀態複製到具有 相同標識符的持久對象上。如果當前沒有與會話關聯的持久實例 ,它將被加載。返回持久的 實例。如果給定實例未保存,請保存其副本並將其作爲新持久實例返回 。給定的實例不會成爲與會話關聯的 。如果關聯映射爲cascade =「merge」,則此操作級聯到關聯的 實例。

所以,由於您是級聯合並您正在合併b。但b未保存,所以b的副本將被保存。所以合併a1會保存b的副本,合併a2會保存b的另一個副本。