【问题标题】:JPA ID GeneratedValue is using Oracle nextValue sequence instead of next valueJPA ID GeneratedValue 正在使用 Oracle nextValue 序列而不是下一个值
【发布时间】:2017-02-01 14:27:06
【问题描述】:

我有一个使用休眠作为 ORM 框架的 Spring Boot 应用程序。它公开了一个 RESTful API,其中一种方法将新消息插入到表中。

我遇到的问题是它调用 Oracle 来检索序列号的 nextval,然后当它插入它使用该池中的第一个数字时,然后当另一个请求进来时,它会采用该值下一个 nextval 而不是使用初始池中的下一个值。所以它应该是 100、101、102 等等……但它却是 100,200,300(分配大小为 100)。

所有 bean 都是单例,包括持久化消息的 DAO。

@Entity
@Table(name = "MESSAGE")
public class Message implements Serializable {

@Id
@SequenceGenerator(name = "MESSAGEID_GENERATOR", sequenceName = "SEQ_MESSAGE", allocationSize = 100)
@GeneratedValue(generator = "MESSAGEID_GENERATOR", strategy = GenerationType.SEQUENCE)
@Column(name = "MESSAGEID", unique = true, nullable = false, precision = 10)
private Long messageid;

}

道:

@Repository
public class MessageDao {

@PersistenceContext(unitName = "ORM_Model")
private EntityManager entityManager;

public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}

public EntityManager getEntityManager() {
    return entityManager;
}

@Transactional
public long save(Message message) {
    entityManager.persist(message);
    entityManager.flush();
    return message.getMessageid();
}
}

persistance.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

<persistence-unit name="ORM_Model"> 

    <description>The IFIS Database Entity Model</description>

    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <class>com.package.Message</class>
    <properties>
        <property name="hibernate.show_sql" value="false" />
        <property name="hibernate.format_sql" value="true" />
        <property name="hibernate.transaction.flush_before_completion" value="true" />
        <property name="hibernate.id.new_generator_mappings" value="true" />                 
    </properties>

</persistence-unit> 

</persistence>

知道这可能是什么问题吗?

问候!

【问题讨论】:

  • 您是否有机会在插入之间重新启动您的应用程序?我没有使用Oracles原生序列,但是当你使用表生成的ID时,JPA会预先分配接下来的100个(allocationSize)id,当你重新启动你的应用程序时,你的ID会从下一个100开始。
  • 不,这是不变的行为——我可以发送两个 HTTP 请求来创建实体,并且每次都会增加 100。我认为这与不同的线程有关,每个线程单独查询下一个序列值,但每个处理数据库的单个实例默认情况下都是一个单例,它们都是一个应用程序的一部分。
  • 这听起来不对。 allocationSize 应该是 JPA 将预分配并保留在内存中的 id 的数量,它应该在从序列中预分配新的 id 之前使用所有这些 id。至少这就是它与TableGenerator 一起工作的方式,它(或多或少)是SequenceGenerator 的数据库不可知版本。
  • 当我使用 JUnit 以不同方式执行该操作并使用该方法两次插入时,ID 会以增量方式分配,但一旦使用 RESTful 控制器包装,它就会执行 100 秒。是否还有其他影响这一点的因素?

标签: spring oracle hibernate jpa


【解决方案1】:

设置您的allocationSize=1 来解决您的问题。

【讨论】:

  • allocationSize=1 表示 JPA 将为每个插入执行 select NEXT_SEQUENCE,这可能会影响性能。预分配的 id 保存在内存中,因此当您重新启动应用程序时,ID 应该只重置为下一个 100。
  • 是的,我不想更改allocationSize,因为这个序列被不同的应用程序使用我不想增加序列查询的负载。还有什么我应该研究的吗?
猜你喜欢
  • 2017-01-06
  • 1970-01-01
  • 2019-08-03
  • 1970-01-01
  • 1970-01-01
  • 2012-02-23
  • 2011-03-05
  • 2012-04-19
相关资源
最近更新 更多