级联合并和持久化之间的JPA OneToOne区别 [英] JPA OneToOne difference between cascade merge and persist

查看:90
本文介绍了级联合并和持久化之间的JPA OneToOne区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下问题.我有3个实体,并且正在单向使用OneToOne:

Entity1

@Entity
public class Entity1 implements Serializable{

   @Id
   @GeneratedValue(strategy= GenerationType.AUTO)
   Long id;
   String name;
   String value;
}

Entity2

@Entity
public class Entity2 implements Serializable {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Long id;

  @OneToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
  Entity1 entity1;
  public Entity1 getEntity1() {
      return entity1;
  }

  String name;
  String value;
}

Entity3

@Entity
public class Entity3 implements Serializable {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  Long id;

  @OneToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
  private Entity1 entity1;

  public Entity1 getEntity1() {
      return entity1;
  }

  public void setEntity1(Entity1 entity1) {
      this.entity1 = entity1;
  }

  String name;
  String value;
}

一个小测试:

public void testApp()
   {
    EntityManager em = TestHibernateUtil.getEntityManager();
    em.getTransaction().begin();
    Entity1 entity1 = new Entity1();
    entity1.name = "Name1";
    entity1.value = "Value1";

    Entity2 entity2 = new Entity2();
    entity2.name = "Name2";
    entity2.value = "Value2";
    entity2.setEntity1(entity1);
    **em.merge(entity2);**// if change that to persist - I get one Entity1

    Entity3 entity3 = new Entity3();
    entity3.name = "Name3";
    entity3.value = "Value3";
    entity3.setEntity1(entity1);
    **em.merge(entity3);** // if change that to persist - I get one Entity1
    em.getTransaction().commit();
 }

因此,请看上面的测试,如果我使用em.merge,则在事务提交后在持久性上下文中确实获得了Entity1的2个实体,如果将其更改为em.persist,则在持久性上下文中获得了Entity1的一个实体.谁能解释我为什么会发生这种情况或指向一些文档?

解决方案

我不想挑战DannyMo的超级答案,但我想补充一点:

持久和合并是为了保留某些对象的一个​​托管实例而设计的.

如果使用persist,则表示该对象尚不存在,因此使其成为唯一的托管实例也不会受到损害.

使用合并时,要考虑到该对象的托管实例可能已经存在.您不想替换该唯一的托管实例,因为某些其他对象可能会引用它,并认为它是托管对象.

如果要在合并后对对象进行操作,则正确的合并应如下所示:

managedObject = em.merge(object); // or just object = em.merge(object) //You cannot do it with persist since it returns null

如果您尝试检查managedObjectobject是否指向同一对象实例并检查if(managedObject == object),则将得到false(当对已管理的对象使用merge且操作被忽略时,可能为true). /p>

如果在对象的过时版本上使用合并,并将其作为参数传递给先前的合并,则jpa不知道如何找到正确的对象,因为它尚无id.假定它是一个新对象,并且将创建新的托管实例.

我是个菜鸟.如果我在任何地方错了,请纠正我.

I have the following question. I have 3 entities and I'm using OneToOne unidirectional:

Entity1

@Entity
public class Entity1 implements Serializable{

   @Id
   @GeneratedValue(strategy= GenerationType.AUTO)
   Long id;
   String name;
   String value;
}

Entity2

@Entity
public class Entity2 implements Serializable {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Long id;

  @OneToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
  Entity1 entity1;
  public Entity1 getEntity1() {
      return entity1;
  }

  String name;
  String value;
}

Entity3

@Entity
public class Entity3 implements Serializable {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  Long id;

  @OneToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
  private Entity1 entity1;

  public Entity1 getEntity1() {
      return entity1;
  }

  public void setEntity1(Entity1 entity1) {
      this.entity1 = entity1;
  }

  String name;
  String value;
}

A small test:

public void testApp()
   {
    EntityManager em = TestHibernateUtil.getEntityManager();
    em.getTransaction().begin();
    Entity1 entity1 = new Entity1();
    entity1.name = "Name1";
    entity1.value = "Value1";

    Entity2 entity2 = new Entity2();
    entity2.name = "Name2";
    entity2.value = "Value2";
    entity2.setEntity1(entity1);
    **em.merge(entity2);**// if change that to persist - I get one Entity1

    Entity3 entity3 = new Entity3();
    entity3.name = "Name3";
    entity3.value = "Value3";
    entity3.setEntity1(entity1);
    **em.merge(entity3);** // if change that to persist - I get one Entity1
    em.getTransaction().commit();
 }

So looking into the test above, if I use em.merge I do get 2 entities of Entity1 in persistence context after transaction commit, if I change it to em.persist then I get one entity of Entity1 in persistence context. Can anybody explain me why that happens or point to some documentation?

解决方案

I would not dream to challenge the uber answer of DannyMo, but I wanted to make an addition:

Persist and merge are designed as a way to keep one managed instance of certain object.

If you use persist it means the object does not exist yet, so making it a unique managed instance doesn't hurt.

When you use merge, you take into consideration that a managed instance of the object may already exist. You don't wanna replace that unique managed instance, because some other object might reference it, believing it is the managed object.

If you want to make operations on the object after the merge, the correct merge would look like this:

managedObject = em.merge(object); // or just object = em.merge(object) //You cannot do it with persist since it returns null

If you tried to check if managedObject and object points to the same object instance checking if(managedObject == object) you will get false (true is possible when you use merge on already managed object and the operation is ignored).

If you use merge on outdated version of object, which you passed as argument to the previous merge, jpa doesn't know how to find the right object since it has yet no id. It is assumed that it is a new object and new managed instance will be created.

I'm quite a rookie. Please correct me if I am wrong anywhere.

这篇关于级联合并和持久化之间的JPA OneToOne区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆