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

时间:2012-04-05 18:09:43

标签: java sql sql-server jpa eclipselink

Q1。:使用

在数据库中应用序列ID有什么区别

:一种。

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

@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

Q2。此链接(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=10还是allocationSize=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 会遭受同样的影响吗?

2 个答案:

答案 0 :(得分:15)

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

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

<强>更新

是否有什么能阻止您使用GenerationType.AUTO?

GenerationType.AUTO确实选择了一种合适的方法来检索实体的ID。因此,在最好的情况下,使用内置功能。但是,您需要检查生成的SQL并查看其中究竟发生了什么 - 因为MSSQL不提供序列,我假设它将使用GenerationType.IDENTITY。

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

答案 1 :(得分:15)

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

B:使用TABLE id generation

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

两者都存在权衡。

IDENTITY不允许预分配,因此在每次INSERT之后需要额外的SELECT,防止批量写入,并且需要刷新来访问id,这可能导致并发性差。

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

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

使用TABLE排序如果你使用100的preallocaiton大小,那么只有每100个插入将锁定序列表中的行,所以只要你通常不同时有100个插入,你就不会受到影响并发性的任何损失。如果您的应用程序执行了大量插入操作,则可能使用1000或更大的值。

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