Hi, the @GeneratedValue annotation must only be used for identifiers. Also, @GenericGenerator is deprecated, so I suggest using the new @ValueGenerationType meta-annotation to define a custom generation strategy that uses your generator. For example:
Thanks for the quick answer.
Isnāt GenerationTiming deprecated as well? I should probably use EventType?
Also, since our MyAppIdGenerator implements org.hibernate.id.IdentifierGenerator, it now throws error Generator class 'MyAppIdGenerator' implements 'IdentifierGenerator' and may not be used with '@ValueGenerationType'
You can customize the annotation members as needed, that one happened to already be in the example I took from but you could put your own values (or none if you donāt need any configuration).
You only need your generator to implement BeforeExecutionGenerator with timing EventType.INSERT and it should work with both identifiers and normal values. IdentifierGenerator is a classic extension point from the early Hibernate days but itās now superfluous (see also its javadoc).
Thanks for the answer, I managed to implement it easily. Itās just EventType thatās substitution for GenerationTiming.
Also, I figured out from the documentation that generator needs to implement BeforeExecutionGenerator.
The trickiest part is about adapting queries for new SQM. E.g.
(COALESCE(:fromTime, '') = '' OR al.createdAt >= :fromTime)
where both al.createdAt and parameter :fromTime are java.time.LocalDateTime, but itās not working anymore, saying:
org.hibernate.query.SemanticException: Literal type 'class java.lang.String' did not match domain type 'java.time.LocalDateTime' nor converted type 'java.util.Date'
and thatās due to SQM I guess, and itās hard to find a (proper) solution for such cases (without explicit type casting).
The trickiest part is about adapting queries for new SQM. E.g.
(COALESCE(:fromTime, '') = '' OR al.createdAt >= :fromTime)
Why are you using coalesce(:fromTime, '') = '' here? That is not valid Hibernate syntax. If you know your parameter is going to be null, just donāt include the restriction in the query with i.e. dynamic Criteria APIs.
Anyway, if you want more specific help with this please create a new topic as itās unrelated with the generator discussion.
You can surely annotate with both @IdGeneratorType and @ValueGenerationType if you want to use the same annotation for both identifiers and normal values, see e.g. Hibernateās @Generated annotation.
Thanks for the quick answer.
Iāve checked @Generated annotation, and it has both @IdGenerationType and @ValueGenerationType, indeed (both using same generator).
Although, it seems that having only @IdGenerationType is enough for both, IDs and regular (generated) values.
Iām sorry for reopening this ticket, but Iāve just found an issue with new generators.
As already mentioned, Iām using the same generator for both PK and regular field, so itās decorated with both @IdGeneratorType and @ValueGenerationType
However, I have a problem with regular fields: as soon as repo.save() executes, entity gets populated its PK and regular guid value. But when transaction commits, PK value stays the same while regular field value gets changed, and I want them both, once generated, to stay the same.
Update of the entity works fine, it does not automatically change this field on every save/update.
When I change column parameter insertable to true, it starts working as expected - once generated, on repo.save(), it does not get changed when transaction commits. However this column definition is the same as it used to be while we were using hibernate v5, where it did not change on transaction commit. Where does the difference in behavior come from?
This was column mapping from hibernate v5:
But when transaction commits, PK value stays the same while regular field value gets changed, and I want them both, once generated, to stay the same
Hibernate has to execute the insert statement and retrieve generated primary keys as soon as the entity is persisted to maintain its identity in the persistence context. Generated values, however, only need to be retrieved once the state of the PC is flushed to the database.
Now, Iām not sure why in your case the generated value is changing, since only calling org.hibernate.Session#persist() once on your entity instance should not cause generated values to be populated more than once. Since it appears youāre using Spring, that might be causing some unnecessary / additional processing when saving.
Yes, Iām using Spring, and @Column annotation is jakarta.persistence annotation.
Ok, thanks for the answer, Iāll continue from there.
I was just wondering if something changed on Hibernate side (between v5 and v6) that caused our existing column mapping to change behavior.