I have a table for generating display id’s that works with hibernate-core 6.4.4:
@Entity
@Table(name = "display_id")
@Getter
@Accessors(chain = true)
@Setter
public class DisplayIdBE implements TenantEntity {
@EmbeddedId private DisplayIdKeyBE id;
@Column(name = "display_id_value", nullable = false)
private long displayIdValue;
@Override
public Long getTenantId() {
return id.getTenantId();
}
}
@Getter
@Embeddable
@EqualsAndHashCode
@AllArgsConstructor
public class DisplayIdKeyBE implements Serializable {
@TenantId
@Column(name = "tenant_id", nullable = false)
private Long tenantId;
@Column(name = "type", nullable = false)
@Enumerated(EnumType.STRING)
private DisplayIdType type;
// For Hibernate
protected DisplayIdKeyBE() {}
}
After I attempt to upgrade to spring-boot 3.4.1, which comes with hibernate-core 6.6.4, I get this error during server startup:
Caused by: org.hibernate.AnnotationException: Property 'com...DisplayIdBE.id.tenantId' is annotated 'interface org.hibernate.annotations.TenantId' which is not an '@IdGeneratorType'
at org.hibernate.boot.model.internal.PropertyBinder.processId(PropertyBinder.java:1450)
at org.hibernate.boot.model.internal.EmbeddableBinder.fillEmbeddable(EmbeddableBinder.java:456)
Can anyone point me in the direction of solving this, or to any release notes that explain what this breaking change is?
While I’m waiting for a response on the hibernate jira ticket, I’d appreciate any ideas for a workaround so I can proceed with the spring-boot upgrade. I really don’t want to have to wait for a new hibernate version, and then a new spring-boot version again. This hibernate version contains fixes for two regressions that I reported last time
Hi @beikov, last time I tried, I couldn’t successfully change the version of hibernate independently of spring-boot, despite having done it in the past. Are there maintained docs for how to do that you can point me to?
Also, if I were to replace my @EmbeddedId with individual fields, what would I do with the repository definition, since I wouldn’t have an ID type for CrudRepository:
public interface DisplayIdRepository extends CrudRepository<DisplayIdBE, DisplayIdKeyBE> {
Edit: just got a response on the hibernate ticket, this is already fixed but in 7.0 . How risky is having a major version difference between what spring-boot was released with and what I’d be forcing Hibernate to?
I don’t know, you should ask this question in Spring forums. The Hibernate project doesn’t have anything to do with Spring. Spring simply uses Hibernate ORM, so usually, nobody in this forum can help you with those integration/setup questions.
I guess you can use the type you specify as @IdClass, but again, I don’t know what Spring Data does here exactly.
You can’t just upgrade to ORM 7, it’s a major version upgrade with breaking changes which also updates to Jakarta Persistence 3.2.
I’ll bring your case up in the next prioritization meeting to see if we can backport this, but maybe you can just try backporting that PR to the 6.6 branch yourself?
Ah, I see. I imagine this is frustrating from both sides. From my perspective I get this package of spring-boot, spring-data, and hibernate that all work seamlessly together and I don’t really know where one stops and the next start. Then it becomes very difficult to get hibernate fixes into my app, and each new version seems to introduce at least one breaking changes that blocks me from upgrading.
This is my attempt to use @IdClass, not sure if I’m doing it right, but it produces the same error:
@Entity
@Table(name = "display_id")
@Getter
@Accessors(chain = true)
@Setter
@IdClass(DisplayIdKeyBE.class)
public class DisplayIdBE implements TenantEntity {
@Id
@TenantId
@Column(name = "tenant_id", nullable = false)
private Long tenantId;
@Id
@Column(name = "type", nullable = false)
@Enumerated(EnumType.STRING)
private DisplayIdType type;
@Column(name = "display_id_value", nullable = false)
private long displayIdValue;
@Override
public Long getTenantId() {
return tenantId;
}
}
public record DisplayIdKeyBE(Long tenantId, DisplayIdType type) {}
Same error:
Property 'com...DisplayIdBE.id.tenantId' is annotated 'interface org.hibernate.annotations.TenantId' which is not an '@IdGeneratorType'
at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808)
at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
That’s unfortunate, but in that case I don’t know if there is a good workaround if the DisplayIdType is not unique on it’s own. You can certainly try to implement tenant handling for this entity manually, but this is going to be cumbersome, so I would rather recommend you to wait for this to get fixed/backported to ORM 6.6.
I was able to re-write the table to not need a ClassId/EmbeddedId. It was a small table, but it will mean we need to take downtime to apply the migration.