Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.hibernate.id.uuid.UuidValueGenerator;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.AnnotationUtil;
import org.hibernate.mapping.GeneratorCreator;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.PersistentClass;
Expand Down Expand Up @@ -412,7 +413,7 @@ private static GeneratorCreator identifierGeneratorCreator(
annotationType
);
callInitialize( annotation, idAttributeMember, creationContext, generator );
callConfigure( creationContext, generator, emptyMap(), identifierValue );
callConfigure( annotation, creationContext, generator, emptyMap(), identifierValue );
checkIdGeneratorTiming( annotationType, generator );
return generator;
};
Expand Down Expand Up @@ -608,7 +609,8 @@ private static void checkVersionGenerationAlways(MemberDetails property, Generat
* call its {@link Configurable#configure(GeneratorCreationContext, Properties)
* configure()} method.
*/
public static void callConfigure(
public static <A extends Annotation> void callConfigure(
A annotation,
GeneratorCreationContext creationContext,
Generator generator,
Map<String, Object> configuration,
Expand All @@ -620,6 +622,9 @@ public static void callConfigure(
creationContext.getRootClass(),
configuration
);
if ( annotation != null ) {
parameters.putAll(AnnotationUtil.getAttributes(annotation));
}
configurable.configure( creationContext, parameters );
}
if ( generator instanceof ExportableProducer exportableProducer ) {
Expand Down Expand Up @@ -773,7 +778,7 @@ private static void instantiateGeneratorBean(
identifierValue.setCustomIdGeneratorCreator( creationContext -> {
final Generator identifierGenerator =
instantiateGenerator( beanContainer, generatorClass( generatorStrategy, identifierValue ) );
callConfigure( creationContext, identifierGenerator, configuration, identifierValue );
callConfigure( null, creationContext, identifierGenerator, configuration, identifierValue );
if ( identifierGenerator instanceof IdentityGenerator) {
identifierValue.setColumnToIdentity();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.internal.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Utility class for various annotation reflection operations.
*
* @author Yanming Zhou
*/
public final class AnnotationUtil {

private static final List<String> excludedMethodNames = List.of( "hashCode", "toString", "annotationType" );

/**
* Retrieve the given annotation's attributes as a {@link Map}, preserving all
* attribute types.
* @param annotation the annotation to retrieve the attributes for
* @return the Map of annotation attributes, with attribute names as keys and
* corresponding attribute values as values (never {@code null})
*/
public static Map<String, Object> getAttributes( Annotation annotation ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Map<String,Object> is what we've just spent years trying to get away from.

try {
Map<String, Object> attributes = new HashMap<>();
for ( Method m : annotation.getClass().getDeclaredMethods() ) {
if ( m.getParameterCount() == 0 && !excludedMethodNames.contains( m.getName() ) ) {
attributes.put( m.getName(), m.invoke( annotation ) );
}
}
return attributes;
}
catch ( Exception ex ) {
throw new RuntimeException( ex );
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@ public class IdGeneratorTypeWithBeanContainerTest {
SimpleEntity entity = new SimpleEntity();
scope.inTransaction(s -> s.persist(entity));
assertThat(entity.id, is(SimpleBeanContainer.INITIAL_VALUE));
SimpleEntity entity2 = new SimpleEntity();
scope.inTransaction(s -> s.persist(entity2));
assertThat(entity2.id, is(entity.id + 2));
}

@Entity
public static class SimpleEntity {
@Id @SimpleId
@Id @SimpleId(step = 2)
long id;
String data;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@
package org.hibernate.orm.test.idgen.userdefined;

import java.util.EnumSet;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicLong;

import org.hibernate.MappingException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.EventType;
import org.hibernate.id.Configurable;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type;

/**
* @author Yanming Zhou
*/
public class SimpleGenerator implements BeforeExecutionGenerator {
public class SimpleGenerator implements BeforeExecutionGenerator, Configurable {

private final AtomicLong sequence;

private long step = 1;

public SimpleGenerator(AtomicLong sequence) {
this.sequence = sequence;
}
Expand All @@ -28,11 +35,16 @@ public Object generate(
Object owner,
Object currentValue,
EventType eventType) {
return sequence.getAndIncrement();
return sequence.getAndAdd(step);
}

@Override
public EnumSet<EventType> getEventTypes() {
return EnumSet.of( EventType.INSERT );
}

@Override
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
this.step = (Long) parameters.get("step");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@
@Retention(RetentionPolicy.RUNTIME)
@IdGeneratorType(SimpleGenerator.class)
public @interface SimpleId {

long step() default 1;

}
Loading