Skip to content

Commit 554ce4f

Browse files
peter1123581321gavinking
authored andcommitted
HHH-8535 Generating an ID with TableGenerator causes a loop if next_val is NULL
1 parent 12118ee commit 554ce4f

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.Properties;
1515
import java.util.function.BiConsumer;
1616

17+
import org.hibernate.HibernateException;
1718
import org.hibernate.LockMode;
1819
import org.hibernate.LockOptions;
1920
import org.hibernate.MappingException;
@@ -584,6 +585,11 @@ private IntegralDataTypeHolder nextValue(
584585
else {
585586
final int defaultValue = storeLastUsedValue ? 0 : 1;
586587
value.initialize( selectRS, defaultValue );
588+
if ( selectRS.wasNull() ) {
589+
throw new HibernateException(
590+
String.format( "%s for %s '%s' is null", valueColumnName, segmentColumnName,
591+
segmentValue ) );
592+
}
587593
}
588594
selectRS.close();
589595
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.schemaupdate.idgenerator;
6+
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.GeneratedValue;
9+
import jakarta.persistence.GenerationType;
10+
import jakarta.persistence.Id;
11+
12+
import jakarta.persistence.TableGenerator;
13+
import org.hibernate.HibernateException;
14+
import org.hibernate.testing.orm.junit.DomainModel;
15+
import org.hibernate.testing.orm.junit.JiraKey;
16+
import org.hibernate.testing.orm.junit.SessionFactory;
17+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
18+
import org.junit.jupiter.api.AfterAll;
19+
import org.junit.jupiter.api.Test;
20+
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
import static org.junit.jupiter.api.Assertions.assertThrows;
23+
24+
@JiraKey(value = "HHH-8535")
25+
@DomainModel(annotatedClasses = {TableGeneratorNextValNullTest.Author.class})
26+
@SessionFactory
27+
public class TableGeneratorNextValNullTest {
28+
29+
@AfterAll
30+
public void dropTestData(SessionFactoryScope scope) {
31+
scope.dropData();
32+
}
33+
34+
@Test
35+
void hhh8535Test(SessionFactoryScope scope) {
36+
37+
// This situation can only happen via human being or bad migration/clone script.
38+
// Simulate this record being updated post table generation.
39+
scope.inTransaction( session -> {
40+
session.createNativeMutationQuery(
41+
"UPDATE generator SET next_val = null where sequence_name = 'Author'"
42+
).executeUpdate();
43+
} );
44+
45+
HibernateException hibernateException = assertThrows( HibernateException.class,
46+
() -> scope.inTransaction( session -> {
47+
Author author = new Author();
48+
session.persist( author );
49+
} ) );
50+
51+
assertEquals( "next_val for sequence_name 'Author' is null", hibernateException.getMessage() );
52+
}
53+
54+
@Entity(name = "Author")
55+
public static class Author {
56+
57+
@Id
58+
@GeneratedValue(strategy = GenerationType.TABLE, generator = "generator")
59+
@TableGenerator(name = "generator", table = "generator")
60+
long id;
61+
}
62+
63+
}

0 commit comments

Comments
 (0)