Oracle 序列生成器 returns 一个负值,当序列号存储在 Java 变量中时

Oracle Sequence generator returns a negative value , when the sequence number is stored in Java variable

我有一个名为 Record ID 的数据库列。这是一个主键,它的值是使用具有以下属性的 oracle 序列生成的 序列详细信息 最小值:1 最大值:999999999999999999999999999 递增:10

在我的 Java 应用程序中,我在应用一些业务逻辑后将记录插入 table。字段 Record ID 的值来自序列生成器

在插入记录之前,在 Java 代码中,我首先将其 ID 设置在一个 Java 长变量中,代码如下(从序列生成器中获取)

public static final String recordSequenceSQL= "SELECT RECORD_ID_SEQ.NEXTVAL FROM DUAL"

Long recordID = jdbcTemplate.queryForObject(SELECT_EVENT_LOG_SEQUENCE_SQL, Long.class);

recordDao.save(recordID , record_name ,age);

recordID 值显示为 -8742538778(在我从序列生成器收到此值之后),它前面有一个负号。

我需要确保没有收到负值。我不确定根本原因,也需要相同的解决方案

要解决问题请尝试以下步骤

检查顺序

与您的应用程序用户联系并运行以下查询:

select SEQUENCE_OWNER, SEQUENCE_NAME, MIN_VALUE, MAX_VALUE, INCREMENT_BY, CACHE_SIZE, LAST_NUMBER
from all_sequences 
where SEQUENCE_NAME = 'RECORD_ID_SEQ';

SEQUENCE_OWNER                 SEQUENCE_NAME                   MIN_VALUE  MAX_VALUE                   INCREMENT_BY CACHE_SIZE LAST_NUMBER
------------------------------ ------------------------------ ---------- ---------------------------- ------------ ---------- -----------
<owner>                        RECORD_ID_SEQ                           1 9999999999999999999999999999           10         20     1202020

重要的值在 LAST_NUMBER 列中,它 大约 您通过调用 NEXTVAL.

获得的值

您将看不到 负面 数字(如果是,请立即联系 Oracle 支持)。

您应该看到的是一个适度的数字,如 5 月示例中所示。

一个潜在的问题是,如果您看到一个数字高于 9223372036854775807,这是 Long 的最大值,但有效数字低于 序列 MAX_VALUE.

但即使在这种情况下,您的 JdbcTemplate 查询也不会得到负数 - 相反,您会得到 Numeric Overflow 异常

Caught: org.springframework.jdbc.UncategorizedSQLException: 
StatementCallback; uncategorized SQLException for SQL [SELECT RECORD_ID_SEQ.NEXTVAL FROM DUAL]; 
SQLstate [99999];
error code [17026]; 
Numeric Overflow; 
nested exception is java.sql.SQLException: Numeric Overflow 

总结

负值的问题很可能出在SELECT_EVENT_LOG_SEQUENCE_SQL查询中(您没有显示)。

进一步的建议

ID 列使用 Long 类型时,将序列的 MAX_VALUE 调整为 LONG 的最大值,请参阅 了解更多信息讨论

如果您预计会大量使用序列,请不要使用 INCREMENT_BY 10,而应使用 1

在 Marmite Bomber 指出问题可能出在 SQL 之后。进行了以下更正 之前
public void saveRecordData(Long RecordId, RecordLog RecordLog) { Object[] parameters = {recordID, RecordLog.getRouteId(), RecordLog.getRecordType().getRecordTypeId(), RecordLog.getOrderId(), RecordLog.getIncomingRecordTimestamp(), RecordLog.getOutgoingRecordTimestamp(), RecordLog.getStatus()}; int[] types = {Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR}; int rowsAffected = jdbcTemplate.update(INSERT_Record_LOG_SQL, parameters, types); }

之后(将 SQL 类型从 TYPES.INTEGER 更改为 TYPES.BIGINT ) public void saveRecordData(Long RecordId, RecordLog RecordLog) { Object[] parameters = {recordID, RecordLog.getRouteId(), RecordLog.getRecordType().getRecordTypeId(), RecordLog.getOrderId(), RecordLog.getIncomingRecordTimestamp(), RecordLog.getOutgoingRecordTimestamp(), RecordLog.getStatus()}; int[] types = {Types.BIGINT, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR}; int rowsAffected = jdbcTemplate.update(INSERT_Record_LOG_SQL, parameters, types); }