Skip to content

Commit ca46d28

Browse files
committed
HHH-10219 - Infinite loop generating IDs if using negative increment
(cherry picked from commit cd7212a)
1 parent deea4ad commit ca46d28

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

hibernate-core/src/main/java/org/hibernate/id/enhanced/NoopOptimizer.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,13 @@ public Serializable generate(AccessCallback callback) {
3737
// reliable as it might be mutated by multipled threads.
3838
// The lastSourceValue field is only accessed by tests,
3939
// so this is not a concern.
40-
IntegralDataTypeHolder value = null;
41-
while ( value == null || value.lt( 1 ) ) {
42-
value = callback.getNextValue();
40+
IntegralDataTypeHolder value = callback.getNextValue();
41+
if ( incrementSize > 0 ) {
42+
while ( value.lt( 1 ) ) {
43+
value = callback.getNextValue();
44+
}
4345
}
46+
4447
lastSourceValue = value;
4548
return value.makeValue();
4649
}

hibernate-core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,28 @@ public void testBasicNoOptimizerUsage() {
4242
assertEquals( 11, sequence.getTimesCalled() ); // an extra time to get to 1 initially
4343
assertEquals( 10, sequence.getCurrentValue() );
4444
}
45+
@Test
46+
public void testBasicNoOptimizerUsageWithNegativeValues() {
47+
// test historic sequence behavior, where the initial values start at 1...
48+
SourceMock sequence = new SourceMock( -1, -1 );
49+
Optimizer optimizer = buildNoneOptimizer( -1, -1 );
50+
for ( int i = 1; i < 11; i++ ) {
51+
final Long next = ( Long ) optimizer.generate( sequence );
52+
assertEquals( -i, next.intValue() );
53+
}
54+
assertEquals( 10, sequence.getTimesCalled() );
55+
assertEquals( -10, sequence.getCurrentValue() );
56+
57+
// test historic table behavior, where the initial values started at 0 (we now force 1 to be the first used id value)
58+
sequence = new SourceMock( 0 );
59+
optimizer = buildNoneOptimizer( -1, 1 );
60+
for ( int i = 1; i < 11; i++ ) {
61+
final Long next = ( Long ) optimizer.generate( sequence );
62+
assertEquals( i, next.intValue() );
63+
}
64+
assertEquals( 11, sequence.getTimesCalled() ); // an extra time to get to 1 initially
65+
assertEquals( 10, sequence.getCurrentValue() );
66+
}
4567

4668
@Test
4769
public void testBasicHiLoOptimizerUsage() {

0 commit comments

Comments
 (0)