/*
* Hibernate OGM, Domain model persistence for NoSQL datastores
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.ogm.backendtck.id;
import static org.fest.assertions.Assertions.assertThat;
import java.util.Arrays;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.ogm.dialect.spi.NextValueRequest;
import org.hibernate.ogm.id.impl.OgmSequenceGenerator;
import org.hibernate.ogm.model.key.spi.IdSourceKey;
import org.hibernate.ogm.model.key.spi.IdSourceKeyMetadata;
import org.hibernate.ogm.utils.GridDialectType;
import org.hibernate.ogm.utils.SkipByGridDialect;
import org.junit.Test;
/**
* Test that the generation of sequences using the table strategy is thread safe.
*
* @author Davide D'Alto
*/
public class SequenceNextValueGenerationTest extends TestNextValueGeneration {
private static final String INITIAL_VALUE_SEQUENCE = "InitialValueSequence";
private static final String THREAD_SAFETY_SEQUENCE = "ThreadSafetySequence";
private static final int INITIAL_VALUE_TEST_FIRST_VALUE = 5;
private static final int THREAD_SAFETY_FIRST_VALUE = 12;
private static final int THREAD_SAFETY_INCREMENT = 3;
@Override
protected IdSourceKey buildIdGeneratorKey(Class<?> entityClass, String sequenceName) {
IdentifierGenerator metadata = generateKeyMetadata( entityClass );
IdSourceKeyMetadata sequenceMetadata = ( (OgmSequenceGenerator) metadata ).getGeneratorKeyMetadata();
if ( dialect.supportsSequences() ) {
return IdSourceKey.forSequence( sequenceMetadata );
}
else {
// Fallback to table generators
return IdSourceKey.forTable( sequenceMetadata, sequenceName );
}
}
@Test
public void testFirstValueIsInitialValue() {
final IdSourceKey generatorKey = buildIdGeneratorKey( InitialValueEntity.class, INITIAL_VALUE_SEQUENCE );
Number sequenceValue = dialect.nextValue( new NextValueRequest( generatorKey, 1, INITIAL_VALUE_TEST_FIRST_VALUE ) );
assertThat( sequenceValue.longValue() ).isEqualTo( Long.valueOf( INITIAL_VALUE_TEST_FIRST_VALUE ) );
}
@Test
@SkipByGridDialect(value = GridDialectType.INFINISPAN)
public void testIncrements() throws InterruptedException {
final IdSourceKey generatorKey = buildIdGeneratorKey( ThreadSafetyEntity.class, THREAD_SAFETY_SEQUENCE );
final NextValueRequest nextValueRequest = new NextValueRequest( generatorKey, THREAD_SAFETY_INCREMENT, THREAD_SAFETY_FIRST_VALUE );
IncrementJob[] runJobs = runJobs( nextValueRequest );
// Verify we got unique results:
int[] allGeneratedValues = new int[INCREASES_PER_TASK * NUMBER_OF_TASKS];
int i = 0;
for ( IncrementJob job : runJobs ) {
int[] generatedValuesPerJob = job.retrieveAllGeneratedValues();
for ( int generatedValue : generatedValuesPerJob ) {
allGeneratedValues[i++] = generatedValue;
}
}
Arrays.sort( allGeneratedValues );
int expectedValue = THREAD_SAFETY_FIRST_VALUE;
for ( int k = 0; k < allGeneratedValues.length; k++ ) {
assertThat( allGeneratedValues[k] ).as( "Unexpected value generated, index: " + k ).isEqualTo( expectedValue );
expectedValue += THREAD_SAFETY_INCREMENT;
}
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{ InitialValueEntity.class, ThreadSafetyEntity.class };
}
@Entity
@Table(name = "INITIAL_VALUE_GENERATOR_SEQUENCE")
private static class InitialValueEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "gen1")
@SequenceGenerator( name = "gen1", sequenceName = INITIAL_VALUE_SEQUENCE, initialValue = INITIAL_VALUE_TEST_FIRST_VALUE )
Long id;
}
@Entity
@Table(name = "THREAD_SAFETY_GENERATOR_SEQUENCE")
private static class ThreadSafetyEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "gen2")
@SequenceGenerator( name = "gen2", sequenceName = THREAD_SAFETY_SEQUENCE, initialValue = THREAD_SAFETY_FIRST_VALUE )
Long id;
}
}