How to use @Generated with @Immutable?

We are running into the following bug in Hibernate: Jira

We basically have the following entity:

@Entity
@Immutable
class AssignmentConfig(
    @field:NaturalId
    @field:ManyToOne(fetch = FetchType.EAGER)
    var assignmentProfile: AssignmentProfile,

    @field:NotBlank(message = "Configuration cannot be null or blank")
    @field:Column(updatable = false, columnDefinition = "JSON")
    var config: String,
) {
    @field:Id
    @field:GeneratedValue(strategy = GenerationType.UUID)
    lateinit var id: AssignmentConfigId

    @field:CreationTimestamp
    lateinit var created: Instant

    @field:Generated
    @field:Column(updatable = false)
    @field:NaturalId
    var revision: Int = -1
}

Where the revision is generated by the database (Through a trigger). However, on refresh, we get a org.hibernate.UnsupportedLockAttemptException: Lock mode not supported, which seems to match that reported bug. Since the bug is a few years old and has not been touched, I don’t expect it to be fixed. Is there any way to work around this such that we can have an immutable entity while still having a generated field?

Hi @LarsSven, are you getting an UnsupportedLockAttemptException? The Jira issue you linked was about explicitly calling refresh, whereas you seem to be getting this error just by annotating a field as @Generated.

While I’m not sure if we can support @Immutable entities with on-execution generated fields, I would definitely say this error is not very self-explanatory and we should produce a better exception. You should try creating a reproducer test case and open a new issue in our tracker for this.

Hi @mbladel

I am indeed getting an UnsupportedLockAttemptException. I indeed do not explicitly call refresh, but my assumption was that this issue is related because if you add @Generated to a field, it will refresh the entity post-insertion to retrieve the database-generated value right? So it implicitly calls refresh.

I am not 100% familiar with the terminology of on-execution generated fields, it is important to note that this field is generated by a database trigger, and not by Hibernate itself. Hibernate simply retrieves the generated field post-insertion.

Would you say this is the same issue as the linked Jira issue?"Or do you think this is something different?

Not really. Hibernate does retrieve the identifier value post-insert, but it does through a very different mechanism than refresh().

That is the definition of on-execution, the value is genered by something that happens when executing the insert statement and Hibernate has to retrieve that value once that completes.

I’m not saying the issues might be related, just that this might be a slightly different case. I would encourage you to create a new Jira issue with a dedicated test case.