jjzjj

java - JPA 与 JTA : Persist entity and merge cascaded child entities

coder 2023-08-27 原文

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

0 或 1 个客户 <-> 0 个或多个产品订单

当持久化客户端实体时,我希望关联的产品订单实体也被持久化(因为它们到“父”客户端的外键可能已更新)。

当然,所有必需的 CASCADE 选项都在客户端设置。但是,如果在引用现有产品订单时第一次持久化新创建的客户端,则它不起作用,如在这种情况下:

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

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

方法 1)“默认”(基于 NetBeans 类模板)

客户:

@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
}

产品订单:

@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);
}

结果:

create() 立即抛出此异常:

Warning: A system exception occurred during an invocation on EJB ClientFacade method public void javaee6test.beans.AbstractFacade.create(java.lang.Object) javax.ejb.EJBException: Transaction aborted ...

Caused by: javax.transaction.RollbackException: Transaction marked for rollback. ...

Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The state-ment was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL120513133540930' defined on 'PRODUCTORDER'. Error Code: -1 Call: INSERT INTO PRODUCTORDER (ID, CLIENT_ID) VALUES (?, ?) bind => [2 parameters bound] Query: InsertObjectQuery(javaee6test.model.ProductOrder[ id=1 ]) ...

Caused by: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL120513133540930' defined on 'PRO-DUCTORDER'. ...

Caused by: org.apache.derby.client.am.SqlException: The statement was aborted be-cause it would have caused a duplicate key value in a unique or primary key con-straint or unique index identified by 'SQL120513133540930' defined on 'PRODUCTOR-DER'.

我不明白这个异常(exception)。编辑()工作正常。但是我想在创建时向客户添加产品订单,所以这是不够的。

方法 2)仅合并()

Generic Persistence Facade 的变化:

// 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);
}

结果:

在 create() 上,EclipseLink 日志输出显示:

Fine: INSERT INTO CLIENT (ID, NAME, ADDRESS_ID) VALUES (?, ?, ?) bind => [3 parameters bound]

但产品订单表上没有“更新”。因此,关系不成立。同样,另一方面,edit() 工作正常。

方法 3) 两种实体类型上的 Id GenerationType.IDENTITY

客户和产品订单类别的变化:

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

结果:

在 create() 上,EclipseLink 日志输出显示:

Fine: INSERT INTO CLIENT (NAME, ADDRESS_ID) VALUES (?, ?) bind => [2 parameters bound]

Fine: values IDENTITY_VAL_LOCAL()

Fine: INSERT INTO PRODUCTORDER (ORDERDATE, CLIENT_ID) VALUES (?, ?) bind => [2 parameters bound]

Fine: values IDENTITY_VAL_LOCAL()

因此,不是建立与添加到客户列表中的产品订单的关系,而是创建并保存一个新的产品订单实体(!),并建立与该实体的关系。同样在这里,edit() 工作正常。

方法 4) 方法 (2) 和 (3) 相结合

结果:与方法(2)相同。

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

最佳答案

您好,我今天遇到了同样的问题,我用这封电子邮件询问 openJPA 邮件列表:

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

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

我不喜欢在 Person 对象中使用合并进行“手动更新”的想法,因为我不知道用户想要更新多少对象(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 方法?

答案是这样的:

看起来你的问题是考试是新的,但人是 现有实体和现有实体在级联持久性时被忽略 手术。我相信这会按预期工作。

只要你的关系设置为 CascadeType.ALL,你总是可以 改变你的 em.persist(exam); em.merge(exam);.那会照顾 坚持新的考试,它也会将合并调用级联到 人。

谢谢, 瑞克


希望对您有所帮助。

关于java - JPA 与 JTA : Persist entity and merge cascaded child entities,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11029260/

有关java - JPA 与 JTA : Persist entity and merge cascaded child entities的更多相关文章

  1. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  2. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  3. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  4. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  5. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  6. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  7. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  8. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

  9. java - Ruby 相当于 Java 的 Collections.unmodifiableList 和 Collections.unmodifiableMap - 2

    Java的Collections.unmodifiableList和Collections.unmodifiableMap在Ruby标准API中是否有等价物? 最佳答案 使用freeze应用程序接口(interface):Preventsfurthermodificationstoobj.ARuntimeErrorwillberaisedifmodificationisattempted.Thereisnowaytounfreezeafrozenobject.SeealsoObject#frozen?.Thismethodretur

  10. java - Java 的 StringReader 的 Ruby 等价物是什么? - 2

    在Java中,可以像这样从一个字符串创建一个IO流:Readerr=newStringReader("mytext");我希望能够在Ruby中做同样的事情,这样我就可以获取一个字符串并将其视为一个IO流。 最佳答案 r=StringIO.new("mytext")和here'sthedocumentation. 关于java-Java的StringReader的Ruby等价物是什么?,我们在StackOverflow上找到一个类似的问题: https://st

随机推荐