Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA和JTA:持久化实体和合并级联子实体_Java_Jpa_Jpa 2.0_Entity Relationship_Jta - Fatal编程技术网

Java JPA和JTA:持久化实体和合并级联子实体

Java JPA和JTA:持久化实体和合并级联子实体,java,jpa,jpa-2.0,entity-relationship,jta,Java,Jpa,Jpa 2.0,Entity Relationship,Jta,我与以下实体类有双向一对多关系: 0或1个客户0或更多产品订单 在持久化客户机实体时,我希望关联的产品订单实体也被持久化(因为它们对“父”客户机的外键可能已经更新) 当然,所有必需的级联选项都是在客户端设置的。但是如果在引用现有产品订单时第一次持久化新创建的客户机,则它不起作用,如本场景中所示: 已创建并保留产品订单“1”。很好 已创建客户端“2”,并将产品订单“1”添加到其产品订单列表中。然后它被持久化。不起作用 我尝试了几种方法,但都没有达到预期的效果。请参见下面的结果。我在这里阅读了所有相

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

0或1个客户0或更多产品订单

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

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

  • 已创建并保留产品订单“1”。很好
  • 已创建客户端“2”,并将产品订单“1”添加到其产品订单列表中。然后它被持久化。不起作用
  • 我尝试了几种方法,但都没有达到预期的效果。请参见下面的结果。我在这里阅读了所有相关的问题,但它们对我没有帮助。我在GlassFish 3.1.2上的ApacheDerby(JavaDB)内存数据库中使用EclipseLink 2.3.0、纯JPA2.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
    }
    
    通用持久性外观:

    // 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);
    }
    
    // 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()立即抛出此异常:

    警告:在EJB上调用期间发生系统异常 ClientFacade方法public void javaee6test.beans.AbstractFacade.create(java.lang.Object) javax.ejb.EJBException:事务中止

    原因: javax.transaction.RollbackException:标记为回滚的事务。

    原因:异常[EclipseLink-4002](Eclipse持久性) 服务-2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException内部 异常:java.sql.SQLIntegrityConstraintViolationException: 状态更新被中止,因为它会导致重复的密钥 标识的唯一或主键约束或唯一索引中的值 通过在“PRODUCTORDER”上定义的“SQL120513133540930”。错误代码:-1 调用:插入PRODUCTORDER(ID,客户端ID)值(?,)bind=> [2参数绑定]查询: InsertObjectQuery(javaee6test.model.ProductOrder[id=1])

    原因: java.sql.SQLIntegrityConstraintViolationException:语句为 已中止,因为这会在唯一的 或主键约束或由标识的唯一索引 “PRO-DUCTORDER”上定义的“SQL120513133540930”

    原因: org.apache.derby.client.am.SqlException:语句被中止 可能是因为它会导致在唯一或 主键约束或由标识的唯一索引 在“PRODUCTOR-DER”上定义了“SQL120513133540930”

    我不理解这个例外。edit()工作正常。但我想在客户机创建时向其添加产品订单,因此这是不够的

    方法2)仅合并()

    对通用持久性外观的更改:

    // 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);
    }
    
    // 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日志记录输出显示:

    精细:在客户机(ID、名称、地址\u ID)中插入值(?、、?) 绑定=>[3个参数绑定]

    但产品订单表上没有“更新”。因此,这种关系尚未建立。另一方面,edit()也可以正常工作

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

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

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

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

    精细:将值(?,)bind=>[2]插入到客户机(名称、地址\u ID)中 参数绑定]

    Fine:values IDENTITY\u VAL\u LOCAL()

    好的:插入到 PRODUCTORDER(ORDERDATE,客户端ID)值(?,)绑定=>[2 参数绑定]

    Fine:values IDENTITY\u VAL\u LOCAL()

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

    近似4)方法(2)和(3)组合

    结果:与方法(2)相同


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

    在ProductOrder实体中使用@Joincolumn注释,请参见下文

       @Entity
       public class ProductOrder implements Serializable, ChildEntity {
       private static final long serialVersionUID = 1L;
    
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       private Long id;
    
       @ManyToOne // owning side
       @JoinColumn(name = "PRODUCTORDER_ID", referencedColumnName = "ID")
       //write your database column names into name and referencedColumnName attributes.
       private Client client;
    
       // other fields, getters and setters
       }
    

    确保您正在设置关系的双方,您不能只将订单添加到客户机,还需要设置订单的客户机。此外,还需要合并已更改的两个对象。如果您只是合并客户机,那么订单的客户机将不会被合并(尽管您的级联导致它被合并)

    持久化不起作用,因为持久化要求被持久化的对象对于持久化上下文是正确的,即不引用分离的对象,它必须引用托管对象


    您的问题来自于您分离对象。如果不拆离对象,则不会出现相同的问题。通常在JPA中,您将创建一个EntityManager,查找/查询您的对象,编辑/持久化它们,调用commit。不需要合并。

    您好,我今天遇到了同样的问题,我向openJPA邮件列表发送此电子邮件:

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

    我试图插入一个新的对象(考试),它引用了另一个对象(人),同时我想更新这个人对象的属性(生日)。虽然我将CascadeType设置为ALL,但更新从未发生。唯一可行的方法是执行持久化,然后执行合并操作。这正常吗?我需要改变什么吗

    我不喜欢这个主意
    // Called when pressing "save" on the "edit..." 
    public void edit(T entity) {
     getEntityManager().merge(entity);}
    
    client.set..(some property to be saved);
    
    productOrder.set..(some property to be saved);
    
    List<ProductOrder> order = new ArrayList<>();
    
    productOrder.setClient(productOrder);
    
    .edit(client) or .edit(productOrder)