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 插入具有复合EmbeddedId(包含另一个EmbeddedId的EmbeddedId)的JPA实体的顺序_Java_Jpa_Jakarta Ee_Openjpa_Websphere 8 - Fatal编程技术网

Java 插入具有复合EmbeddedId(包含另一个EmbeddedId的EmbeddedId)的JPA实体的顺序

Java 插入具有复合EmbeddedId(包含另一个EmbeddedId的EmbeddedId)的JPA实体的顺序,java,jpa,jakarta-ee,openjpa,websphere-8,Java,Jpa,Jakarta Ee,Openjpa,Websphere 8,我正在从事WebSphere8.5.5(OpenJPA2.2.3)中的一个项目,该项目需要通过一个大型JPA注释实体模型进行级联创建和合并。当通过在父级上调用EntityManager.merge()或在提交事务时触发刷新来合并子级时,我们遇到了一个非常特殊的问题。详情如下: 实体映射的相关部分: EntityA有一个到EntityB的单间 EntityB有一个到EntityC的oneToMany EntityC有一个到EntityD的oneToMany 它们都有双向映射。实体A和B具有单列主键

我正在从事WebSphere8.5.5(OpenJPA2.2.3)中的一个项目,该项目需要通过一个大型JPA注释实体模型进行级联创建和合并。当通过在父级上调用EntityManager.merge()或在提交事务时触发刷新来合并子级时,我们遇到了一个非常特殊的问题。详情如下:

实体映射的相关部分:

  • EntityA有一个到EntityB的单间
  • EntityB有一个到EntityC的oneToMany
  • EntityC有一个到EntityD的oneToMany
  • 它们都有双向映射。实体A和B具有单列主键。实体C有一个复合主键,其中包含实体B主键的外键。实体D有一个复合键,其中包含实体C的复合键。请参见下面的映射

    @Entity
    @Table(name="TableA")
    public class EntityA extends BaseEntity {
    
        @Id
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLE_A_ID_GEN")
        @SequenceGenerator(name="TABLE_A_ID_GEN", sequenceName="TABLE_A_ID", allocationSize=1)
        @Column(name="TABLE_A_ID")
        private Integer id;
    
        @OneToMany(fetch=FetchType.LAZY, mappedBy="entityA", cascade=CascadeType.ALL)
        private List<EntityB> entityBList;
    
        ...
    
    }
    
    @Entity
    @Table(name="TableB")
    public class EntityB extends BaseEntity {
    
        @Id
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLE_B_ID_GEN")
        @SequenceGenerator(name="TABLE_B_ID_GEN", sequenceName="TABLE_B_ID", allocationSize=1)
        @Column(name="TABLE_B_ID")
        private Integer id;
    
        @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
        @JoinColumn(name="TABLE_A_ID")
        private EntityA entityA;
    
        @OneToMany(fetch=FetchType.LAZY, mappedBy="entityB", cascade=CascadeType.ALL)
        private List<EntityC> entityCList;
    
        ...
    
    }
    
    @Entity
    @Table(name="TableC")
    public class EntityC extends BaseEntity {
    
        @EmbeddedId
        private EntityC_PK id = new EntityC_PK();
    
        @MapsId("entityB_Id")
        @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
        @JoinColumn(name="TABLE_B_ID")
        private EntityB entityB;
    
        @OneToMany(fetch=FetchType.LAZY, mappedBy="entityC", cascade=CascadeType.ALL)
        private List<EntityD> entityDList;
    
        ...
    
    }
    
    @Embeddable
    public class EntityC_PK implements BaseComponent {
    
        @Column(name="TABLE_B_ID", nullable = false, updatable = false)
        private Integer entityB_Id;
    
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLE_C_ID_GEN")
        @SequenceGenerator(name="TABLE_C_ID_GEN", sequenceName="TABLE_C_ID", allocationSize=1)
        @Column(name="TABLE_C_ID")
        private Integer entityC_Id;
    
        ...
    
    }
    
    @Entity
    @Table(name="TABLE_D")
    public class EntityD extends BaseEntity {
    
        @EmbeddedId
        private EntityD_PK id = new EntityD_PK();
    
        @MapsId("entityC_Id")
        @JoinColumns({
            @JoinColumn(name = "TABLE_B_ID"),
            @JoinColumn(name = "TABLE_C_ID")})
        @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
        private EntityC entityC;
    
        ...
    
    }
    
    @Embeddable
    public class EntityD_PK implements BaseComponent {
    
        @Embedded
        private EntityC_PK entityC_Id;
    
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLE_D_ID_GEN")
        @SequenceGenerator(name="TABLE_D_ID_GEN", sequenceName="TABLE_D_ID", allocationSize=1)
        @Column(name="TABLE_D_ID")
        private Integer entity_id;
    
        ...
    
    }
    
    @实体
    @表(name=“TableA”)
    公共类EntityA扩展了BaseEntity{
    @身份证
    @GeneratedValue(策略=GenerationType.SEQUENCE,generator=“表A\U ID\U GEN”)
    @SequenceGenerator(name=“TABLE\u A\u ID\u GEN”,sequenceName=“TABLE\u A\u ID”,allocationSize=1)
    @列(name=“TABLE\u A\u ID”)
    私有整数id;
    @OneToMany(fetch=FetchType.LAZY,mappedBy=“entityA”,cascade=CascadeType.ALL)
    私有列表实体列表;
    ...
    }
    @实体
    @表(name=“TableB”)
    公共类EntityB扩展了BaseEntity{
    @身份证
    @GeneratedValue(策略=GenerationType.SEQUENCE,generator=“TABLE_B_ID_GEN”)
    @SequenceGenerator(name=“TABLE\u B\u ID\u GEN”,sequenceName=“TABLE\u B\u ID”,allocationSize=1)
    @列(name=“TABLE_B_ID”)
    私有整数id;
    @manytone(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
    @JoinColumn(name=“TABLE\u A\u ID”)
    私人实体a实体a;
    @OneToMany(fetch=FetchType.LAZY,mappedBy=“entityB”,cascade=CascadeType.ALL)
    私有列表实体列表;
    ...
    }
    @实体
    @表(name=“TableC”)
    公共类EntityC扩展了BaseEntity{
    @嵌入ID
    私有EntityC_PK id=新EntityC_PK();
    @MapsId(“实体Id”)
    @manytone(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
    @JoinColumn(name=“TABLE_B_ID”)
    私人实体b实体b;
    @OneToMany(fetch=FetchType.LAZY,mappedBy=“entityC”,cascade=CascadeType.ALL)
    私有列表实体列表;
    ...
    }
    @可嵌入
    公共类EntityC_PK实现BaseComponent{
    @列(name=“TABLE_B_ID”,null=false,updateable=false)
    私有整数实体b_Id;
    @GeneratedValue(策略=GenerationType.SEQUENCE,generator=“TABLE\u C\u ID\u GEN”)
    @SequenceGenerator(name=“TABLE\u C\u ID\u GEN”,sequenceName=“TABLE\u C\u ID”,allocationSize=1)
    @列(name=“TABLE_C_ID”)
    私有整数实体Id;
    ...
    }
    @实体
    @表(name=“Table_D”)
    公共类EntityD扩展了BaseEntity{
    @嵌入ID
    private EntityD_PK id=new EntityD_PK();
    @MapsId(“实体Id”)
    @连接柱({
    @JoinColumn(name=“TABLE_B_ID”),
    @JoinColumn(name=“TABLE_C_ID”)})
    @manytone(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
    私人实体实体;
    ...
    }
    @可嵌入
    公共类EntityD_PK实现BaseComponent{
    @嵌入
    私有实体PK实体Id;
    @GeneratedValue(策略=GenerationType.SEQUENCE,generator=“TABLE\u D\u ID\u GEN”)
    @SequenceGenerator(name=“TABLE\u D\u ID\u GEN”,sequenceName=“TABLE\u D\u ID”,allocationSize=1)
    @列(name=“TABLE\u D\u ID”)
    私有整数实体_id;
    ...
    }
    
    工作原理:

    您可以对实体A(附加所有子实体)调用EntityManager.persist(),模型将正确级联persist

    什么不起作用:

    如果实例化实体A并调用EntityManager.persist(entityA),然后在EntityManager.merge(entityA)(或在提交事务时允许隐式合并)时添加子项、子项等,它将无法以正确的顺序执行INSERT语句。为了使事情更加混乱,插入的顺序在单元测试的重复执行中是不一致的。它尝试在实体C之前插入实体D失败

    问题是:

    如何在合并时更正JPA注释以强制执行正确的插入顺序(以及更新/删除)

    编辑1: 插入/删除顺序非常关键,因为数据库强制执行带有约束的外键关系。

    首先让我声明(也许我说的是显而易见的,对不起),您应该针对您的场景查看JPA规范……。嵌入式有时有不同的规则。接下来,您声明了“EntityManager.create()”,但我认为您的意思是.persist?你后来谈到合并,所以你是说,合并?不管是哪种方式,我都建议您坚持使用.persist,如果您希望持久化新实体而不是合并。虽然合并不是非法的,但合并通常用于合并分离的实体等

    有了这些,让我进入你问题的核心,给你一个可能有助于你的订单的财产。您没有在文本中声明ddl是否包含外键约束。既然你关心秩序,我就认为你有这样的限制。如果您这样做,OpenJPA对这个约束一无所知,因此也不知道如何正确地排序。默认情况下,您不能依赖SQL的顺序,而顺序的随机性正是我所期望的。然而,如果您需要以支持FK约束的方式对事物进行排序,那么您需要允许OpenJPA“了解”您的约束。为此,需要在persistence.xml文件中设置此属性(或者可以将其设置为JVM自定义属性):

    
    
    此属性允许OpenJPA检查您的模式,这样做可以了解您的FK约束。有了这些知识,OpenJPA可以正确地排序SQL

    最后,如果没有FK约束,但希望以某种方式对SQL排序,则可能需要使用以下命令:

    <property name="openjpa.jdbc.UpdateManager" value="operation-order"/>  
    
    
    
    <property name="openjpa.jdbc.UpdateManager" value="operation-order"/>