Hello,
Defining a property like this with an enum set converter to string:
@Convert(converter = app.masterchefworld.utils.enumconverters.Efficiency.class)
@Column(columnDefinition = "text", name = "efficiency")
private Set<Efficiency> efficiencies;
and a query:
@NamedQuery(name="recipes.findSpecial", query= """
select recipe
from Recipe recipe
where recipe.efficiencies like ?1 escape '!'
""")
when I try to execute:
Query query = em.createNamedQuery("recipes.findSpecial", Recipe.class);
query.setParameter(1, "%asdf%");
List<Recipe> result = query.getResultList();
I get:
Argument [%asdf%] of type [java.lang.String] did not match parameter type [java.util.Set (n/a)]
I think this is related to this [HHH-17693] - Hibernate JIRA and this [HHH-17790] - Hibernate JIRA.
Is there a workaround?
I’m using Hibernate 6.4.8
Thanks,
Hugo
Workaround is to model it like this:
@Column(columnDefinition = "text", name = "efficiency")
private String efficienciesText;
private transient Set<Efficiency> efficiencies;
@PostLoad
void postLoad() {
efficiencies = new app.masterchefworld.utils.enumconverters.Efficiency().convertToEntityAttribute(efficienciesText);
}
@PrePersist
@PreUpdate
void prePersistUpdate() {
efficienciesText = new app.masterchefworld.utils.enumconverters.Efficiency().convertToDatabaseColumn(efficiencies);
}
Thanks @beikov, after tested it, I see that “efficiencies” is empty in @PreUpdate. It seams that transient properties are not available in @PreUpdate because JPA creates a new instance to merge it. JPA transient information lost on create - Stack Overflow
Indeed, @PreUpdate
is called on the managed object after copying the state over from the object passed to merge
, but only if the passed object is not already managed.
So either you apply changes to the managed object and don’t use merge
, or you call this prePersistUpdate
method yourself before calling merge
.
You can just map the column twice though:
@Convert(converter = app.masterchefworld.utils.enumconverters.Efficiency.class)
@Column(columnDefinition = "text", name = "efficiency")
private Set<Efficiency> efficiencies;
@Column(columnDefinition = "text", name = "efficiency", insertable = false, updatable = false)
private String efficienciesText;
And use that other attribute in your query
select recipe
from Recipe recipe
where recipe.efficienciesText like ?1 escape '!'
Thanks @beikov With this I think I can fix the problem!