Hello there!
We’ve been updating to Springboot 3 and Hibernate 6. We’ve got a relatively “simple” table set up, but with some subtle complexities.
The table we’ve mapped in Hibernate 5 has a number of columns. There’s a data
column, which contains a large JSONB blob, and a source
column, which denotes the type of row this is. Depending on the source
, the JSON blob in the data
row could be subtly different. So we previously marshalled it to different objects.
In the Java, we have a parent object, lets call it Animal, which has all of the columns on it (including source
, but not data
). We than have specific implementation class for each source, which has it’s own definition for data
.
For example:
@Entity
@DiscriminatorValue("Dog")
public class Dog extends Animal {
@Column(name = "data")
@JdbcTypeCode(SqlTypes.JSON)
private DogData data;
public Dog() {
}
....
Previously we could use the AnimalDao
and pass it a Specification
, which part of the query would use includes
and use the given sources
to filter the result.
However, since updating to Hibernate 6, this has stopped working. Instead, what seems to happen is Hibernate picks the first JSON type it can find alphabetically, and attempts to use it to marshal DogData
. If you have Cat
with CatData
, it’ll find and use CatData
instead of DogData
. This then causes a problem, as per this stack trace error:
org.springframework.orm.jpa.JpaSystemException: Could not set value of type [com.example.application.CatData] :
com.example.application.Dog.data (setter)
There seems to be an issue with how Hibernate figures out which JSON marshaller to use. I’ve tried creating a UserType
, and it’s ignored when using the generic AninmalDao
but not when using the DogDao
.
Has anyone else experienced this? Any suggestions on how to fix?