【问题标题】:What are the difference between: sequence id using JPA @TableGenerator, @GeneratedValue vs database Auto_Increment有什么区别:使用 JPA @TableGenerator 的序列 ID,@GeneratedValue 与数据库 Auto_Increment
【发布时间】:2012-04-19 11:53:36
【问题描述】:

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;
    ...
}

我的系统高度并发。由于我的 DB 是 Microsoft SQL server,我认为它不支持@SequenceGenerator,所以我必须留在@TableGenerator,这很容易出现并发问题。

Q2. 此链接 (http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Advanced_Sequencing) 表明 B 可能会遇到并发问题,但我不理解建议的解决方案。如果有人能向我解释如何避免 B 的并发问题,我将不胜感激。这是他们解决方案的 sn-p:

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 作为我的提供者;我必须按照上面的建议去做吗?

Q3.如果B遇到并发问题,A是否也会遇到同样的问题?

【问题讨论】:

    标签: java sql sql-server jpa eclipselink


    【解决方案1】:

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

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

    更新:

    有什么让您远离使用 GenerationType.AUTO 的原因吗?

    GenerationType.AUTO 确实选择了一种适当的方式来检索您的实体的 id。所以在最好的情况下使用内置功能。但是,您需要检查生成的 SQL 并查看那里到底发生了什么 - 因为 MSSQL 不提供序列,我假设它会使用 GenerationType.IDENTITY。

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

    【讨论】:

    • 当你说:The challenge is to transfer this feature to be used by JPA.,你是指@GeneratedValue的使用吗?所以我尝试在表中设置列AUTO_INCREMENT,然后尝试创建倍数Person。使用id 正确创建的第一个人最初是 5,但它会为第 2 个人生成异常。Null or zero primary key encountered in unit of work clone。能不能不直接把id注解@Id,不加@GeneratedValue,然后持久化实体对象,让AUTO_INCREMENT的数据库PK处理?
    • 你能展示你的映射吗?您应该使用@GeneratedValue 告诉JPA 实现该ID 已得到处理。这里有一个链接可以帮助您开始:developerscrappad.com/408/java/java-ee/…
    【解决方案2】:

    A:使用 IDENTITY id 生成,@GeneratedValue(IDENTITY)

    B:使用 TABLE id 生成

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

    两者都有取舍。

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

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

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

    如果使用 TABLE 排序,如果您使用 100 的预分配大小,那么只有每 100 次插入才会锁定序列表中的行,因此只要您通常不会同时有 100 次插入,您就不会受到影响任何并发损失。如果您的应用程序执行大量插入操作,则可能使用 1000 或更大的值。

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

    【讨论】:

    • 您关于TABLE sequencing a preallocaiton size 的信息对我有很大帮助,因为我决定使用TABLE 序列进行实施。你应该有这个赏金,我会再等一会儿,看看是否有人有其他想法可以贡献,如果没有,我会给你赏金。非常感谢
    猜你喜欢
    • 2018-04-29
    • 2019-10-03
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 2011-08-06
    相关资源
    最近更新 更多