Sipios' Spring Boot JPA Search - Querying Enum - java

I am using Spring Boot (2.7.3) and Sipios' library for Spring Search for JPA Entities (https://github.com/sipios/spring-search).
I am trying make a search based on one of my class's enum fields, but receive the following error:
InvalidDataAccessApiUsageException: Parameter value [FIRST] did not match expected type [*.MY_ENUM (n/a)];
To make it clear through an example, let's say I have an entity-class "MyClass" which has a field "MY_ENUM enumField", and MY_ENUM has the values ('FIRST', 'SECOND', 'THIRD').
I am trying to query for all MyClass entries that have the value 'FIRST' in their enumField.
The enumField is annotated with #Enumerated(EnumType.STRING).
For those familiar with the specific library, my HTTP request is: localhost:8080/controller/search?search=enumField:FIRST.
I have also tried putting the FIRST query param in single & double quotes but the result was the same.
I have traced the problem to Hibernate's org.hibernate.query.spi.QueryParameterBindingValidator, method isValidBindValue().
Method isValidBindValue() checks whether value "FIRST" is of MY_ENUM type.
More specifically, the line that effectively causes the exception is expectedType.isInstance(value), where expectedType is "class MY_ENUM" and value is "FIRST", which evaluates to false and thus the error message - values checked via Intellij's debugger.
I have tried it with versions 0.2.3 & 0.2.4 of sipios/spring-search.
I saw that version 0.2.3 should support querying enums but I couldn't find any relative examples on how to do it, so it may be possible I have misunderstood how to use spring-search, but I would expect Spring Boot to recognise the "FIRST" string as an instance of MY_ENUM type.

Related

ElasticsearchRepository - Modify the #Query value

Currently I'm working with a ElasticsearchRepository and Springboot Data. I can write a simple method with a simple Query annotation:
#Query("{\"bool\":{\"must\":[{\"match\":{\"_resource\":\"?0\"}}]}}")
List<Activity> findByResource(String resource);
However, the Activity index might have different, multiple fields (varying from line to line in logstash). So, I might need to add multiple match clauses. I was testing adding a second parameter that would contain the rest of the params (if any) like this:
#Query("{\"bool\":{\"must\":[{\"match\":{\"_resource\":\"?0\"}}?1]}}")
List<Activity> findByResource(String resource, String additionalClauses);
the second parameter could look like this:
String additional = ",{\"match\":{\"_method\":\"GET\"}}
However, I get this exception when calling the endpoint with the service:
Elasticsearch exception [type=x_content_parse_exception, reason=[1:60] [bool] failed to parse field [must]]; nested exception is ElasticsearchStatusException[Elasticsearch exception [type=x_content_parse_exception, reason=[1:60] [bool] failed to parse field [must]]]; nested: ElasticsearchException[Elasticsearch exception [type=json_parse_exception, reason=Unexpected character ('\\' (code 92)): was expecting double-quote to start field name\n at [Source: (ByteArrayInputStream); line: 1, column: 62]]];
I understand that what I was trying to do isn't not the ideal way to use the #Query annotation (I don't think it's even allowed to do what I'm trying), so:
Is there a different way to accomplish this?
Is #Query que only option I have? How could I do it then?
Cheers.
Passing additional query components as parameter in this way is not possible. If a parameter is a String it will be quoted and escaped before being inserted into the value of the #Query annotation. This created String is then used to build a StringQuery.
You will need to create one of the Query variants (see https://docs.spring.io/spring-data/elasticsearch/docs/4.3.0/reference/html/#elasticsearch.operations.queries for details), probably a StringQuery and pass that to the ElasticsearchOperations.

Spring data mongodb interface configuration and use of _class field

I'm migrating from MySQL to mongodb and wondering about couple of things:
1> when using JpaRepository interface and MySQL i need to provide configuration(in my case in the form of settings in application.properties) for it to work otherwise the application fails with a message saying configuration of DataSource failed... but with MongoRepository the application works without any sort of configuration and the data is saved to the default test db. I'd like to know how and where spring makes the initial configuration of the Driver , db name, user and password to use.
2> All objects saved through MongoRepository contain an additional _class field with FQN of the object,
in section 4.6.2 Type mapping the docs say that it needs to do that because
the values held inside that property have to be read in correctly when retrieving the object.
which i didnt fully understand and would love an elaboration on. i created a test with User collection and a few documents in it, some with _class and some without(by inserting the objects using the mongoshell) and the test application had no problem retrieving the User objects that didnt have the _class field and printing them to the console. I also changed the _class field for the collections that had it to "" and it still printed them correctly so how does Spring uses it?

spring jpa not able to locate the field when there are two consecutive capital letter coming in the same field name of a query method

When the method name contains two consecutive capital letters in the same field name, the spring-jpa is not able to locate the same field in the table
Examples query method:
1.findByTypeAndASiteNameOrTypeAndZSiteName
2.findByAColumnOrBColumn
The above query method explanation
(type AND a_site_name) or (type AND z_site_name)
a_column or b_column
The same query method was working up to 2.1.7.RELEASE of spring boot and spring-data-jpa. Currently, I am migrating to 2.2.5.RELEASE and I am facing the issue.
Exception:
Unable to locate Attribute with the the given name [ASiteName] on this ManagedType [com.example.h2demo.domain.Subscriber]
This has changed from Spring Boot 2.1.8 to 2.1.9
According to the Java Beans specification the getter and setter for aColumn must be:
public String getaColumn
public void setaColumn(String aColumn)
So the query method must be:
findByaColumnOrbColumn
Read more about this in the JIRA of Spring Data JPA
https://jira.spring.io/browse/DATACMNS-1589

Spring-Data elastic search repo count with custom #Query annotation not working "Expected 1 but found 30 results"

For my application I have to perform a custom count on elastic, I want to use the #Query annotation for this in the ElasticsearchCrudRepository we use. When I use the following signature:
#Query("CUSTOM BOOL QUERY HERE")
long countItemsCustom();
This leads to a java.lang.IllegalArgumentException: Expected 1 but found 30 results Exception since it is executed as an query instead of an count. For spring-data-cassandra we have a special #CountQuery annotation to solve this issue. Is there a similar solution in spring-data-elasticsearch ?
I could use the elastic client or template to perform a custom query and get the results, but I prefer using the existing repository interface for this if possible.
No, that's not possible at the moment. The ElasticsearchStringQuery class checks the return type of the method that is annotated with the #Query annotation and then executes the ElasticsearchOperations.queryFor...() method that is appropriate for the method's return type. These are queries for data and not for the count.
I created an issue in the Spring Data Elasticsearch Jira to have this feature added.

spring jdbc template returns an empty result

I have the following code
resultList = daoResources.jdbcTemplate.query(sql, selectParams, new BeanPropertyRowMapper(resultClass));
SQL when run with the selectParams against database, I get result. The selecting fields name of the sql matches with the fields in the resultClass too. But for above code, I get an empty resultList.
Where could be the problem?
Debugging is your friend in this scenario. I suggest you enable debug logs for jdbc template to see what sql's and bind parameters are sent to database. Below is from the 3.0.x reference doc
All SQL issued by this class is logged at the DEBUG level under the
category corresponding to the fully qualified class name of the
template instance (typically JdbcTemplate, but it may be different if
you are using a custom subclass of the JdbcTemplate class).

Categories