'While fetching data using RSQL for enum type resulting InvalidDataAccessApiUsageException
I have an Entity with attribute type enum. I am trying to run query using RSQL. My query is
siteType==LOCAL
But it is resulting below exception because in query I am passing siteType as String Value but in JPA siteType is enum.
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [LOCAL] did not match expected type [com.dataservice.api.site.wrapper.SiteType (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [permanent] did not match expected type [com.dataservice.api.site.wrapper.SiteType (n/a)]
@Entity
@Table(name = "SITE")
public class Site {
@Id
@Column(name = "ID", updatable = false, nullable = false)
private Long id;
@Column(name = "NAME")
private String name;
@Column(name = "SITE_TYPE")
@Enumerated(EnumType.STRING)
private SiteType siteType;
Enum:
public enum SiteType {
LOCAL, ONDEMAND;}
RSQL code :
Node rootSearchNode = new RSQLParser().parse(searchQuery);
Specification<Site> siteSearchSpec = rootSearchNode.accept(new CustomRsqlVisitor<Site>());
resultSitesList = siteDataService.getSitesBySearchQuery(siteSearchSpec);
Solution 1:[1]
The problem is it does not know how to map the string representation of the enum to the actual enum type. I faced the same problem and worked around it by changing the Entity as:
@Column(name = "SITE_TYPE")
private String siteType;
public void setSiteType(SiteType siteType) {
this.siteType = siteType.name();
}
public SiteType getSiteType() {
return Enum.valueOf(SiteType.class, siteType);
}
Solution 2:[2]
private List<Object> castArguments(Root<T> root) {
List<Object> args = new ArrayList<Object>();
Class<? extends Object> type = root.get(property).getJavaType();
for (String argument : arguments) {
if (type.equals(Integer.class)) {
args.add(Integer.parseInt(argument));
} else if (type.equals(Long.class)) {
args.add(Long.parseLong(argument));
} else if (type.equals(SiteType.class)) {
args.add(SiteType.valueOf(argument));
} else {
args.add(argument);
}
}
return args;
}
Taking the suggestion in the comment. Add another else-if check for your own enum type.
Solution 3:[3]
If you want to use an Enum type in RSQL query, cast Enum argument like below:
private List<Object> castArguments(final Root<T> root) {
final Class<? extends Object> type = root.get(property).getJavaType();
final List<Object> args = arguments.stream().map(arg -> {
if (type.equals(Integer.class)) {
return Integer.parseInt(arg);
} else if (type.equals(Long.class)) {
return Long.parseLong(arg);
} else if (type.isEnum()) {
return Enum.valueOf((Class<? extends Enum>) type, arg);
} else {
return arg;
}
}).collect(Collectors.toList());
return args;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Selçuk Cihan |
| Solution 2 | selimssevgi |
| Solution 3 | heelha |
