简体   繁体   English

休眠一对多关联可保存重复项

[英]Hibernate one-to-many association saves duplicates

I have a class A that can have an association to multiple B s (one-to-many): 我有一个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;
 }
}

and class B storing a reference to A : 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;
 }
}

When I now execute the following code Hibernate will save two entries in tables b both having the name b1 . 当我现在执行以下代码时,Hibernate将在表b保存两个条目,两个条目的名称均为b1 I do not know how to avoid this or what I am doing wrong. 我不知道如何避免这种情况或我做错了什么。

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();

I think you should be saving a1 and a2 instead of merging them. 我认为您应该保存a1和a2而不是合并它们。 From the javadocs, this is what merge does. 从javadocs,这就是合并的作用。

Copy the state of the given object onto the persistent object with the same identifier. 将给定对象的状态复制到具有相同标识符的持久对象上。 If there is no persistent instance currently associated with the session, it will be loaded. 如果当前没有与该会话关联的持久性实例,则将其加载。 Return the persistent instance. 返回持久实例。 If the given instance is unsaved, save a copy of and return it as a newly persistent instance. 如果给定实例未保存,请保存的副本并将其作为新的持久实例返回。 The given instance does not become associated with the session. 给定的实例不与会话关联。 This operation cascades to associated instances if the association is mapped with cascade="merge". 如果关联是用cascade =“ merge”映射的,则此操作将级联到关联的实例。

So, since you are cascading merge you are merging b. 因此,由于您是级联合并,因此您正在合并b。 But b is unsaved, so a copy of b will be saved. 但是b未保存,因此将保存b的副本。 So merging a1 will save a copy of b, and merging a2 will save another copy of b. 因此,合并a1将保存b的副本,而合并a2将保存b的另一个副本。

您可以通过创建A和B之间的映射表(然后有两个条目)来实现此目的,因为每个B都将对其A的引用存储在列中,并且作为数据库状态的第一种常规形式,您只有原子值因此,没有哪一行B行在同一列中具有两个A主键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM