使用 JPA @TableGenerator 的序列 id 与数据库Auto_Increment之间的区别是什么:@GeneratedValue

2022-09-03 12:17:59

Q1.: 在数据库中应用序列 Id 有什么区别

一个。

CREATE TABLE Person
(
   id long NOT NULL AUTO_INCREMENT
   ...
   PRIMARY KEY (id)
)

B.

@Entity
public class Person {
    @Id
    @TableGenerator(name="TABLE_GEN", table="SEQUENCE_TABLE", pkColumnName="SEQ_NAME",
        valueColumnName="SEQ_COUNT", pkColumnValue="PERSON_SEQ")
    @GeneratedValue(strategy=GenerationType.TABLE, generator="TABLE_GEN")
    private long id;
    ...
}

我的系统是高度并发的。由于我的数据库是Microsoft SQL服务器,我认为它不支持,所以我必须留下来,这容易出现并发问题。@SequenceGenerator@TableGenerator

问题 2.这里的这个链接(http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Advanced_Sequencing)表明B可能会受到并发问题的困扰,但我不明白提出的解决方案。如果有人能向我解释如何避免B的并发问题,我将不胜感激。以下是他们的解决方案的一个片段:

If a large sequence pre-allocation size is used this becomes less of an issue, because the sequence table is rarely accessed.

Q2.1: 我们在这里谈论的分配大小是多少?我应该做还是?allocationSize=10allocationSize=100

Some JPA providers use a separate (non-JTA) connection to allocate the sequence ids in, avoiding or limiting this issue. In this case, if you use a JTA data-source connection, it is important to also include a non-JTA data-source connection in your persistence.xml.

Q2.2: 我使用 EclipseLink 作为我的提供者;我必须按照上面的建议去做吗?

问题 3.如果 B 存在并发问题,A 是否也存在相同的问题?


答案 1

使用TableGenerator,下一个id值将在表中查找和维护,并且基本上由JPA而不是数据库维护。当您有多个线程访问数据库并尝试找出 id 字段的下一个值时,这可能会导致并发问题。

auto_increment类型将使您的数据库关注表的下一个ID,即。它将在运行插入时由数据库服务器自动确定 - 这肯定是并发安全的。

更新:

有什么能让你远离使用GenerationType.AUTO吗?

GenerationType.AUTO 会选择适当的方法来检索实体的 ID。因此,在最好的情况下,使用内置功能。但是,您需要检查生成的STL,看看那里到底发生了什么 - 由于MSSQL不提供序列,我认为它将使用GenerationType.IDENTITY。

如前所述,auto_increment列负责分配下一个id值,即。那里没有并发问题 - 即使有多个线程并行处理数据库。挑战在于将此功能转移给 JPA 使用。


答案 2

答:使用身份 ID 生成,@GeneratedValue(IDENTITY)

B:使用表 ID 生成

JPA支持三种类型,IDENTITY, SEQUENCE and TABLE.

两者都有权衡。

IDENTITY 不允许预分配,因此每次 INSERT 后都需要一个额外的 SELECT,从而防止批量写入,并且需要刷新才能访问 ID,这可能会导致并发性较差。

TABLE 允许预分配,但序列表上的锁可能存在并发问题。

从技术上讲,SEQUENCE ID生成是最好的,但并非所有数据库都支持它。

使用 TABLE 排序,如果使用 100 的预定位大小,则每 100 个插入项中只有一个插入项会锁定序列表中的行,因此,只要您通常不同时有 100 个插入项,就不会在并发性方面遭受任何损失。如果应用程序执行大量插入,则可能使用 1000 或更大的值。

EclipseLink 将使用单独的事务进行 TABLE 排序,因此将减少任何与序列表锁定的并发问题。如果您使用的是 JTA,那么需要指定一个非 jta 数据源来执行此操作,并在持久性.xml属性中配置序列连接池。


推荐