My classes use an ID like
@Id @Generated(GenerationTime.INSERT) @GeneratedValue private Integer id;
This works perfectly for H2 (supporting sequences) and gets interpreted for MySql by creating a helper table hibernate_sequence
. Using this answer, everything looks the way I want, especially using a single sequence for all tables.
One thing seems to be wrong: There are multiple rows in the helper table. My id
is declared in a @MappedSuperclass
and during initialization, for each concrete class this line gets executed:
insert into hibernate_sequence values ( 1 )
This is obviously wrong: there is a line per table there and each contains the same value (initially one; when changed, they all change in the same way, as the SQL is update hibernate_sequence set next_val=? where next_val=?
, so it effects all the rows in the same way).
It's harmless, but I wonder: Is it a bug or am I doing something wrong?
If you want to make it works you need to use other strategy for now:
@GenericGenerator(
name = "table_generator",
strategy = "org.hibernate.id.enhanced.TableGenerator"
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "table_generator")
What about org.hibernate.id.enhanced.SequenceStyleGenerator
:
I believe there is an issue in how hibernate initializes shared single row sequence table.
For hibernare 5.0.6.Final Source of the issue lies in org.hibernate.boot.internal.InFlightMetadataCollectorImpl
class
in
private void processExportableProducers(MetadataBuildingContext buildingContext) {
// for now we only handle id generators as ExportableProducers
final Dialect dialect = getDatabase().getJdbcEnvironment().getDialect();
final String defaultCatalog = extractName( getDatabase().getDefaultNamespace().getName().getCatalog(), dialect );
final String defaultSchema = extractName( getDatabase().getDefaultNamespace().getName().getSchema(), dialect );
for ( PersistentClass entityBinding : entityBindingMap.values() ) {
if ( entityBinding.isInherited() ) {
continue;
}
// ***************************************************************************
// For Instance, it does not filter out the same entityBinding.getIdentifier()
// and make initialization multiple time
// ***************************************************************************
handleIdentifierValueBinding(
entityBinding.getIdentifier(),
dialect,
defaultCatalog,
defaultSchema,
(RootClass) entityBinding
);
}
for ( Collection collection : collectionBindingMap.values() ) {
if ( !IdentifierCollection.class.isInstance( collection ) ) {
continue;
}
handleIdentifierValueBinding(
( (IdentifierCollection) collection ).getIdentifier(),
dialect,
defaultCatalog,
defaultSchema,
null
);
}
}
Presume there is a Base
class annotated with @MappedSuperclass
. There are also A
and B
classes extending Base
class; If you annotate Id
field in Base
class with @SequenceGenerator
, all subclasses of Base
share the same sequence generator and will increament/use the same sequence in the database for their ids. This is ofcourse harmless but results in ugly numbers for ids :
@MappedSuperclass
public class Person {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="id_gen")
@SequenceGenerator(name="id_gen", sequenceName="a_seq", allocationSize=1)
private Long id;
}
@Entity
public class A extends Base {
}
@Entity
public class B extends Base {
}
This is what their ids look like after adding A, then B, then A :
A{id=1, name='...'}
B{id=2, name='...'}
A{id=3, name='...'}
A nicer way would be having a fresh sequence for each table which can be implemented through assigning different sequence generators for different subclasses :
@MappedSuperclass
public class Person {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="id_gen")
private Long id;
}
@Entity
@SequenceGenerator(name="id_gen", sequenceName="a_seq", allocationSize=1)
public class A extends Base {
}
@Entity
@SequenceGenerator(name="id_gen", sequenceName="b_seq", allocationSize=1)
public class B extends Base {
}
Their ids will look like this after adding A, then B, then A :
A{id=1, name='...'}
B{id=1, name='...'}
A{id=2, name='...'}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With