Override how JSON fields dirty checking is done (equality)

Hi,

I have fields annotated with @JdbcTypeCode(SqlTypes.JSON) (the configured formatter is using my own Jackson ObjectMapper) and I would like to define how they are compared to each other for dirty checking.
I would like that equality is done based on the json serialized value of the object instead of using the Java in-memory equals/hashCode.

Is that something that is possible?

The best that you can do is provide a custom JavaType implementation, which you can then specify with @JavaType(MyJavaType.class) on the persistent attribute.

Right, it makes sense, and how can I define such a type that is variable w.r.t. the declared type of the field in the entity class?

I can see that JsonJavaType is instantiated based on the declared type in BasicValue.determineReflectedJavaType. Is there any way to get access to that information (or similar information) from within the constructor of my custom JavaType that I would introduce?

Or I see that the JavaType is instantiated using getManagedBeanRegistry().getBean( javaTypeClass ).getBeanInstance() in BasicValueBinder.normalSupplementalDetails, maybe this mechanism allows for injecting such information?

Or will @JavaType refuse any class that cannot be instantiated without a parameter-less constructor?

Thank you for your help

You will have to create a separate JavaType implementation for every type that you want to support. We could also enhance the FormatMapperBasedJavaType to use the string representation for the equals check if we see that the persistent attribute class does not declare an equals method. You can create an improvement request on Jira for that if you want.

1 Like

Sorry, I’m not that experienced with hibernate. Could you provide a very brief example for me, since I’m having trouble to follow, but I also face the same problem. I have a custom ObjecttMapper and I need to do the dirty check based on the string value of the json-values.

You write a custom implementation of org.hibernate.type.descriptor.java.JavaType for your java class and annotate the persistent field with @JavaType(MyJavaType.class).
The custom implementation can then implement the areEqual method by serializing both arguments to a String with your ObjectMapper and comparing the String objects.
It’s probably best if your custom class extends from AbstractClassJavaType and just override the necessary methods.

1 Like

Thanks for your quick and helpful reply! :slightly_smiling_face:
I do understand now, but while I was implementing your suggested solution I also found org.hibernate.type.descriptor.java.spi.JsonJavaType. Would it be possible to utilize this class to save some lines of code?

No it’s not possible, because that is a special JavaType which has further context that a user defined implementation can not inject.

1 Like

Hi, it took me a bit of time but here is the feature request: [HHH-17992] - Hibernate JIRA

I think it’s best that as a Hibernate user, I can choose to use comparison via serialization or not, but I don’t really trust implicit/magic approaches where the behaviour depends on if equals is declared or not.

1 Like