当前位置: 首页 > 知识库问答 >
问题:

使用JTA的JPA:持久实体和合并级联子实体

有玄天
2023-03-14

我与以下实体类有一个双向的一对多关系:

当然,所有必需的级联选项都是在客户端设置的。但如果在引用现有产品订单时首次持久化新创建的客户端(如本场景所示),则它将不起作用:

  1. 已创建并持久化产品订单“%1”。工作正常。
  2. 已创建客户端“%2”,并将产品订单“%1”添加到其产品订单列表中。然后它被持久化。不起作用。

我尝试了几个apporach,但没有一个显示出预期的结果。请参阅下面的结果。我在这里阅读了所有相关的问题,但它们对我没有帮助。我在GlassFish 3.1.2上的Apache Derby(JavaDB)内存数据库上使用EclipseLink 2.3.0、纯JPA2.0注释和JTA作为事务类型。实体关系由JSF GUI管理。对象级关系管理工作(除了持久化之外),我用JUnit测试对它进行了测试。

客户:

@Entity
public class Client implements Serializable, ParentEntity {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(mappedBy = "client", cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},
            fetch= FetchType.LAZY)
    private List<ProductOrder> orders = new ArrayList<>();

    // other fields, getters and setters
}

ProductOrder:

@Entity
public class ProductOrder implements Serializable, ChildEntity {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne // owning side
    private Client client;

    // other fields, getters and setters
}

泛型持久性外观:

// Called when pressing "save" on the "create new..." JSF page
public void create(T entity) {
    getEntityManager().persist(entity);
}

// Called when pressing "save" on the "edit..." JSF page
public void edit(T entity) {
    getEntityManager().merge(entity);
}

原因:javax.Transaction.rollbackException:标记为回滚的事务。...

原因:异常[EclipseLink-4002](Eclipse Persistence Services-2.3.0.V20110604-R9504):org.Eclipse.Persistence.exceptions.DatabaseException内部异常:java.sql.sqlintegrityConstraintViolationException:状态被中止,因为它会导致由“ProductOrder”上定义的“SQL120513133540930”标识的唯一或主键约束或唯一索引中的键值重复。错误代码:-1调用:插入PRODUCTORDER(ID,CLIENT_ID)值(?,?)bind=>[2个参数绑定]查询:InsertObjectQuery(javaEE6Test.Model.ProductOrder[ID=1])...

原因:java.sql.SQLINTegrityConstraintViolationException:该语句已中止,因为它将导致在“Pro-DuctOrder”上定义的“SQL120513133540930”标识的唯一或主键约束或唯一索引中出现重复的键值。...

原因:org.apache.derby.client.am.sqlexception:该语句被中止,原因是它会导致由“Productor-der”上定义的“SQL120513133540930”标识的唯一或主键con-straint或唯一索引中的键值重复。

我不明白这个例外。edit()工作良好。但我希望在客户机创建时向其添加产品订单,因此这是不够的。

方法2)仅merge()

对泛型持久性外观的更改:

// Called when pressing "save" on the "create new..." JSF page
public void create(T entity) {
    getEntityManager().merge(entity);
}

// Called when pressing "save" on the "edit..." JSF page
public void edit(T entity) {
    getEntityManager().merge(entity);
}

但产品订单表上没有“更新”。这样,关系就不成立了。另一方面,edit()也可以正常工作。

Apporach 3)两个实体类型上的Id GenerationType.Identity

对客户端和产品订单类别的更改:

...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...

精细:值IDENTITY_VAL_LOCAL()

精细:插入PRODUCTORDER(ORDERDATE,CLIENT_ID)值(?,?)绑定=>[2个参数绑定]

精细:值IDENTITY_VAL_LOCAL()

我的问题是:有没有办法实现上面描述的场景?如何归档?我希望继续使用JPA(没有特定于供应商的解决方案)。

共有1个答案

董翰池
2023-03-14

嗨,我今天遇到了同样的问题,我向openJPA邮件列表询问这封邮件:

嗨。我在插入和更新同一实体中的引用时遇到问题。

我正在尝试插入一个引用另一个对象(Person)的新对象(Exam),同时我想更新Person对象的属性(birthDate)。尽管我将CascadeType设置为All,但更新从未发生。唯一的方法是执行persist,然后执行merge操作。这正常吗?我必须改变什么吗??

我不喜欢在Person对象中使用merge进行“手动更新”的想法,因为我不知道用户要更新多少对象(Exam的子对象)。

实体:

public class Exam{  
   @ManyToOne(cascade= CascadeType.ALL)
   @JoinColumn(name = "person_id")
   public Person person;
......
}

public class Person{
    private Date birthDate;
   @OneToMany(mappedBy = "person")
    private List<Exam> exams
.......
}

public class SomeClass{
   public void someMethod(){
      exam = new Exam()
      person.setBirthDate(new Date());
      exam.setPerson(person); 
      someEJB.saveExam(exam);
   }
}

public class someEJB(){

   public void saveExam(Exam exam){
        ejbContext.getUserTransaction().begin();
        em.persist(exam);
        //THIS WORKS
        em.merge(exam.getPerson());
        ejbContext.getUserTransaction().commit();       
   }

}

我必须对每个子对象使用MERGE方法吗?

谢谢,瑞克

希望这能帮到你。

 类似资料:
  • 我有两个这样的 JPA 实体: 如您所见, 字段在 和 之间形成了多对多关系,因此我认为使用 来指定字段的级联是合适的。但是,当尝试在映射中保留具有几个 值的 时,我得到以下异常: 显然,EclipseLink 不会级联我的 实例的持久性。我应该如何注释 以使级联持久工作?

  • 我试图集成Spring和JSF,我坚持使用对象。我不想处理事务(begin-commit等) 经过一些谷歌,我可以找到一个答案,给我需要在这个链接 我使用eclipselink作为ORM和Oracle 11g数据库,并使用带有Maven的Glassfish Server3.1。我更喜欢Spring配置的注释。我用 相关类中的注释。我的名称是E_DefterManagementPU,我的事务类型是J

  • 问题内容: 我最近开始玩Play!Java框架1.2.3版(最新)。在测试框架时,尝试在名为的Hibernate实体中保留对象时遇到了一个奇怪的问题。地图对象映射长到Hibernate的实体,我呼吁,随着申报 我的问题如下:按照我的注释创建正确的表。但是,当对象持久化时,其中的数据就不会! 这是我用于实体的代码。首先是: 这里是: 这是我用来测试设置的课程: 表演!框架会自动为HTTP请求创建一个

  • 问题内容: 我最近开始玩Play!Java框架1.2.3版(最新)。在测试框架时,尝试在名为的Hibernate实体中保留对象时遇到了一个奇怪的问题。地图对象映射长到Hibernate的实体,我呼吁,随着申报 我的问题如下:按照我的注释创建正确的表。但是,当对象持久化时,其中的数据就不会! 这是我用于实体的代码。首先是: 这里是: 这是我用来测试设置的课程: 表演!框架会自动为HTTP请求创建一个

  • 主要内容:JPA级联持久化示例,输出结果级联持久化用于指定如果实体持久化,则其所有关联的子实体也将被持久化。 以下语法用于执行级联持久性操作 - JPA级联持久化示例 在这个例子中,我们将创建两个相互关联的实体类,但要建立它们之间的依赖关系,我们将执行级联操作。 这个例子包含以下步骤 - 第1步: 在包下创建一个名为的实体类,其中包含属性:,,以及标记为级联规范的类型的对象。 文件: StudentEntity.java - 第2步:

  • 我有以下问题。我有3个实体,我使用的是一个单向实体: 一个小测试: 因此,看看上面的测试,如果我使用,在事务提交之后,确实会在持久性上下文中获得Entity1的两个实体,如果我将其更改为,则会在持久性上下文中获得Entity1的一个实体。有谁能解释一下为什么会发生这种情况或者指出一些文档吗?