【发布时间】: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