1

I have an unusual situation which requires that I obtain unique identifiers from an Oracle sequence without actually saving a row to the table which relies on the sequence.

My entity:

@Table(name = 'SUBMISSION')
@Entity(name = 'Submission')
class Submission {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 'submissionSeq')
    @SequenceGenerator(
        name = 'submissionSeq',
        sequenceName = 'SUBMISSION_SEQ',
        allocationSize = 50
    )
    @Column(name = 'SUBMISSION_ID', nullable = false)
    Long submissionId
    ...

My repository:

@Repository
interface SubmissionRepository extends JpaRepository<Submission, Long> {

    @Query(value = 'SELECT submission_seq.NEXTVAL FROM DUAL', nativeQuery = true)
    Long getNextSequenceValue()
}

As you can see, the identifier for the SUBMISSION table is generated from an Oracle sequence, whose allocation size is set to 50. The JPA provider (Hibernate) is caching those IDs in memory to avoid a call to the database to obtain a sequence value each time a Submission record is persisted.

To get a single value from this sequence, I am using a Spring Data native query. However, because the sequence is set to increment by 50, this wastes 49 unique IDs each time this native query is invoked.

Is there a way to obtain a submissionId from the cached values stored within Hibernate's pool of allocated IDs instead of wasting IDs?

2
  • Hibernate does not provide any public API to directly access or fetch Ids from its internal sequence cache or pre allocated pool. The sequence caching mechanism in hibernate is strictly internal and is tightly controlled by the SequenceStyleGenerator If you dont want to use hibernate sequence generator then I guess other way is manually fetch Ids from the sequence by creating a separate sequence with increment by 1 Commented Jul 4 at 7:14
  • SequenceStyleGenerator delegates the generation to its Optimizer for which there is a public Optimizer getOptimizer(), the problem is to get your hands on the generator used... highly depends on the Hibernate version used. Commented Jul 5 at 8:14

1 Answer 1

0

Tested with Hibernate-core-6.5.2:

import jakarta.persistence.EntityManager;

import org.hibernate.generator.Generator;
import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.id.enhanced.DatabaseStructure;

final Generator gen = sessionFactory.getIdentifierGenerator("fully_qualified_name_of_entity_class");
final Optimizer opt = ((SequenceStyleGenerator)gen).getOptimizer();
final DatabaseStructure dbs = ((SequenceStyleGenerator)gen).getDatabaseStructure() ;
        
final Serializable id = opt.generate(dbs.buildCallback(session));

With Hibernate-core-5.6.12:

import javax.persistence.EntityManager;

import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.enhanced.DatabaseStructure;
import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.id.enhanced.SequenceStyleGenerator;


final IdentifierGenerator gen = sessionFactory.getIdentifierGenerator("fully_qualified_name_of_entity_class");
final Optimizer opt = ((SequenceStyleGenerator)gen).getOptimizer();
final DatabaseStructure dbs = ((SequenceStyleGenerator)gen).getDatabaseStructure() ;
        
final Serializable id = opt.generate(dbs.buildCallback(session));

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.