Java 在JPA中处理ID表的最佳解决方案是什么?

Java 在JPA中处理ID表的最佳解决方案是什么?,java,oracle,jpa,Java,Oracle,Jpa,您好,就我的工作而言,我正在尝试正确处理一个用于保持其他表之间一致性的表。 架构师决定在Oracle数据库12c上提供此解决方案: 由于数据量很大,每个实体上都有一个分区列控制的分区。实体id由每个实体类型生成 我尝试使用JPA实体继承来简化数据库中的插入。这段代码是我找到的最好的解决方案: @Entity @Table(name="ID_TABLE") @Inheritance(strategy=InheritanceType.JOINED) @DiscriminatorColumn(nam

您好,就我的工作而言,我正在尝试正确处理一个用于保持其他表之间一致性的表。
架构师决定在Oracle数据库12c上提供此解决方案:


由于数据量很大,每个实体上都有一个分区列控制的分区。实体id由每个实体类型生成

我尝试使用JPA实体继承来简化数据库中的插入。这段代码是我找到的最好的解决方案:

@Entity
@Table(name="ID_TABLE")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="Entity_Type", discriminatorType=DiscriminatorType.STRING)
public abstract class IdTable implements Serializable {
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    protected IdTablePK id;
}

@Embeddable
public class IdTablePK implements Serializable {
    @Column(name="Partition_col")
    protected short partitionCol;

    @Column(name="Entity_ID")
    protected long entityID;

    @Column(name="Version_ID")
    protected short versionID;

    @Column(name="Entity_Type")
    protected String entityType;
}

@Entity
@DiscriminatorValue("01")
@Table(name = "ENTITY1")
@PrimaryKeyJoinColumns({
    @PrimaryKeyJoinColumn(name="Partition_col1", referencedColumnName="Partition_col"),
    @PrimaryKeyJoinColumn(name="Entity_ID1", referencedColumnName="Entity_ID"),
    @PrimaryKeyJoinColumn(name="Version_ID1", referencedColumnName="Version_ID"),
    @PrimaryKeyJoinColumn(name="Entity_Type1", referencedColumnName="Entity_Type")
})
public class Entity1 extends IdTable{
...
}
问题是,我认为select命令的性能非常差,因为JPA自动生成了内部联接:

select
    entity1.Partition_col1
    entity1.Entity_ID1
    entity1.Version_ID1
    entity1.Entity_Type1
    entity1.Data1
from
    entity1
inner join
    table_ID 
    on entity1.Partition_col=table_ID.Partition_col
        entity1.Entity_ID=table_ID.Entity_ID
        entity1.Version_ID=table_ID.Version_ID
        entity1.Entity_Type=table_ID.Entity_Type
where
    entity1.Partition_col1=?
    and entity1.Entity_ID1=?
    and entity1.Version_ID1=?
    and entity1.Entity_Type1=?
我担心这种关系的表现对吗?有没有更好的解决方案或方法来避免select命令上的连接

**编辑**:克里斯给了我一个主意。如果IdTable实体的所有相关实体都是这样连接的呢

@Entity
@Table(name="ID_TABLE")
public class IdTable implements Serializable {
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    protected IdTablePK id;

    @OneToOne(fetch=FetchType.LAZY, cascade = CascadeType.PERSIST, optional = true)
    @JoinColumns({
        @JoinColumn(name="Partition_col1", referencedColumnName="Partition_col"),
        @JoinColumn(name="Entity_ID1", referencedColumnName="Entity_ID"),
        @JoinColumn(name="Version_ID1", referencedColumnName="Version_ID"),
        @JoinColumn(name="Entity_Type1", referencedColumnName="Entity_Type")
    })
    private Entity1 e1;
    ...
}

@Embeddable
public class IdTablePK implements Serializable {
    @Column(name="Partition_col")
    protected short partitionCol;

    @Column(name="Entity_ID")
    protected long entityID;

    @Column(name="Version_ID")
    protected short versionID;

    @Column(name="Entity_Type")
    protected String entityType;
}

@Entity
@Table(name = "ENTITY1")
public class Entity1 implements Serializable{
    @EmbeddedId
    protected Entity1PK id;
    ...
}

@Embeddable
public class Entity1PK implements Serializable {
    @Column(name="Partition_col1")
    protected short partitionCol1;

    @Column(name="Entity_ID1")
    protected long entityID1;

    @Column(name="Version_ID1")
    protected short versionID1;

    @Column(name="Entity_Type1")
    protected String entityType1;
}
IdTable插入到Entity1之前,请求Entity1时没有到IdTable的直接链接


现在,是否可以使用Entity1序列来填充IdTable中的实体ID?

使用第二次尝试中的Entity1PK(您可以删除注释),尝试:


将任何表单的排序批注放在要使用排序的字段上。

使用第二次尝试中的Entity1PK(您可以删除批注),尝试:


将任何形式的排序注释放在您希望使用排序的字段上。

您的解决方案很优雅,但这不是我想要的。这里的结果是,JPA在加载Entity1之前在IdTable中查找,而不会在Entity1之前持久化IdTable实体。问题是我们想要使用Entity1序列,但我们必须在之前保持IdTable。我正在编辑我的问题,以添加我们进行的第二次尝试。如果您正在寻找,EclipseLink将为您保留IdTable。您只需要在映射上设置cascade.Persist cascade选项,这将导致找到引用的IdTable并将其与Entity1一起插入,并使用IdTable中的值填充Entity1字段。我不清楚你在问什么,但如果你想在Entity1中设置值来填充IdTable,就以上面的模型为例切换参考方向,基本上只是重命名上面的两个类。我花了一段时间才理解这个项目。正如我所说,我们必须插入Entity1,其id由sequencer设置,但必须在之前设置IdTable。另外,在读取Entity1时,我们不希望以任何方式读取IdTable。此外,日食是不允许在这个项目。。。它看起来像一条死胡同!我认为我离上一次编辑的最佳解决方案不远了,我正在寻找在JPA(或JPQL)中获得Entity1 sequencer值的最佳方法,我正在尝试这样做:我不确定您所指的EclipseLink是死路一条,但它只是JPA提供者的一个例子;我最喜欢的一个,因为我参与了开源项目。我应该说JPA和任何一家提供商都是一样的,我从来没有说过EclipseLink。我说的是我正在寻找的解决方案,但有一些限制。开源项目团队所做的工作总是给我留下深刻印象,如果我误解了自己,我很抱歉。关于解决方案,我们最终将所有实体放在TableID中,以保持级联模式,然后我们只读取实体。您的解决方案很优雅,但这不是我想要的。这里的结果是,JPA在加载Entity1之前在IdTable中查找,而不会在Entity1之前持久化IdTable实体。问题是我们想要使用Entity1序列,但我们必须在之前保持IdTable。我正在编辑我的问题,以添加我们进行的第二次尝试。如果您正在寻找,EclipseLink将为您保留IdTable。您只需要在映射上设置cascade.Persist cascade选项,这将导致找到引用的IdTable并将其与Entity1一起插入,并使用IdTable中的值填充Entity1字段。我不清楚你在问什么,但如果你想在Entity1中设置值来填充IdTable,就以上面的模型为例切换参考方向,基本上只是重命名上面的两个类。我花了一段时间才理解这个项目。正如我所说,我们必须插入Entity1,其id由sequencer设置,但必须在之前设置IdTable。另外,在读取Entity1时,我们不希望以任何方式读取IdTable。此外,日食是不允许在这个项目。。。它看起来像一条死胡同!我认为我离上一次编辑的最佳解决方案不远了,我正在寻找在JPA(或JPQL)中获得Entity1 sequencer值的最佳方法,我正在尝试这样做:我不确定您所指的EclipseLink是死路一条,但它只是JPA提供者的一个例子;我最喜欢的一个,因为我参与了开源项目。我应该说JPA和任何一家提供商都是一样的,我从来没有说过EclipseLink。我说的是我正在寻找的解决方案,但有一些限制。开源项目团队所做的工作总是给我留下深刻印象,如果我误解了自己,我很抱歉。关于解决方案,我们最终将所有实体放在TableID中,以级联模式持久化,然后只读取实体。
@Entity
@Table(name="ID_TABLE")
@IdClass(Entity1PK.class)
public class IdTable implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @OneToOne(fetch=FetchType.LAZY, cascade = CascadeType.PERSIST, optional = true)
    @JoinColumns({
        @JoinColumn(name="Partition_col1", referencedColumnName="Partition_col"),
        @JoinColumn(name="Entity_ID1", referencedColumnName="Entity_ID"),
        @JoinColumn(name="Version_ID1", referencedColumnName="Version_ID"),
        @JoinColumn(name="Entity_Type1", referencedColumnName="Entity_Type")
    })
    private Entity1 e1;
    ..
 }

@Entity
@Table(name = "ENTITY1")
@IdClass(Entity1PK.class)
public class Entity1 {

  @Id
  @Column(name="Partition_col1")
  protected short partitionCol1;

  @Id
  @GeneratedValue(strategy=GenerationType.TABLE)
  @Column(name="Entity_ID1")
  protected long entityID1;

  @Id
  @Column(name="Version_ID1")
  protected short versionID1;

  @Id
  @Column(name="Entity_Type1")
  protected String entityType1;
})