Hi,
I have upgraded to hibernate 6.6 from 6.2 and found, that @GenericGenerator is deprecated. I am using native strategy, so some databases are using sequences and others identity. I need this for backward compatibility.
GenerationType.IDENTITY is always generating identity and disabling identity in dialect throws, GenerationType.AUTO is selecting sequences for SQL Server. Is there option to alter behaviour of AUTO strategy in dialect or some supported way to use native generator?
The supported way to specify a custom generator is using @IdGeneratorType meta-annotation, see the user guide for more details and examples on how to rework your mappings.
Only way is to create custom generator? I was thinking about that, but this is complicated - delegate either to identity or sequence generator - how should I know current dialect?
Dialect has nothing to do with this. If you wish to use identity or sequence generators, just annotated either @GeneratedValue( strategy = IDENTITY ) or @GeneratedValue( strategy = SEQUENCE ).
I’m afraid that’s not possible with native Hibernate functionality, you’re just going to need to create a custom generator that implements your specific business logic.
Hi I also have the same problem with @GenericGenerator(name = “native_generator”, strategy = “native”), I need to support PostgesSql and Ms SQL together but as hibernate 6.5 deprecated GenericGenerator annotation, which annotation could be replacement of GenericGenerator with strategy = “native”? PostgesSql need ID with sequence and Ms SQL needs Auto increment ID. @jezbera Have you found solution for it?
I have used dirty way - custom IdentifierGeneratorFactory, that replaces sequences with identity based on dialect (it will break with future hibernate):
Here a possible solution with @IdGeneratorType (case when ID is of type Long). Use identity for mssql and sequence for the others. Change configure() if you want another behaviour
public class SequenceOrIdentityIdentifierGenerator extends IdentityGenerator implements IdentifierGenerator, OnExecutionGenerator {
private static final long serialVersionUID = -6394994123485461850L;
private String sequenceName;
private String sequenceCallSyntax;
private boolean useIdentity = false;
public SequenceOrIdentityIdentifierGenerator(SequenceOrIdentity config, Member annotatedMember, CustomIdGeneratorCreationContext context) {
this.sequenceName = config.name();
}
@Override
public void configure( Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
final JdbcEnvironment jdbcEnvironment = serviceRegistry .getService(JdbcEnvironment.class);
final Dialect dialect = jdbcEnvironment.getDialect();
if(dialect instanceof AbstractTransactSQLDialect) { // An abstract base class for Sybase and MS SQL Server dialects.
useIdentity = true;
} else {
useIdentity = false;
sequenceCallSyntax = dialect.getSequenceSupport().getSequenceNextValString(sequenceName);
}
}
@Override
public Serializable generate( SharedSessionContractImplementor session, Object obj) {
return Session.class.cast(session)
.createNativeQuery(sequenceCallSyntax, Long.class)
.uniqueResult()
.longValue();
}
@Override
public boolean generatedOnExecution() { // true if the value is generated by the database, or false if it is generated in Java
return useIdentity ? true : false;
}
@Override
public boolean referenceColumnsInSql(Dialect dialect) {
return useIdentity ? super.referenceColumnsInSql(dialect) : false; // maybe useful only for OnExecutionGenerator,,,
}
@Override
public boolean writePropertyValue() {
return useIdentity ? false : true; // maybe not useful for sequences
}
@Override
public EnumSet<EventType> getEventTypes() {
return EventTypeSets.INSERT_ONLY;
}
}