Get parameters out from QueryDSL Predicate Object - java

I use QueryDSL predicate object with a spring REST endpoint to retrieve and query param values.
#GetMapping("/{subjectId}/students")
#RolesAllowed( {Roles.PLATFORM_ADMIN, Roles.USER})
public List<StudentResponse> getAllStudents(#PathVariable final String subjectId,
#QuerydslPredicate(root = Student.class) final Predicate predicate) {
final Predicate searchPredicate = studentPredicate()
.predicate(predicate)
.subjectId(subjectId)
.build();
return studentService.findBySubjectId(subjectId, searchPredicate);
}
student Class contains studentId and studentName attributes;
Now, if someone invokes https://hostname/{subjectId}/students?studentId=1234&studentName=test
Then above code generates the predicate object with param values. But I need to get above 2 param values out from predicate object for further processing apart from the db querying. I don't see any supportive method from predicate object to retrieve values out. So how can I do it?

There is no straightforward way to do this.
However You can try this.
predicate.toString(); ---> This would print user.Studentid=1234 && user.studentName=test
From this, you can do a string split.
Another way is with
predicate.getClass()); ----> This will give you the class name like
class com.querydsl.core.types.PredicateOperation (in case of more than one query conditions)
class com.querydsl.core.types.dsl.BooleanOperation (in case of single query condition).
With this you could typecast predicate to corresponding type and then do getArgs().

Related

Filter on an Integer field in Realm

If the id attribute in an object is of type Integer, how do I filter the query to return all objects whose id contains part of a query. i.e. what is the equivalent Realm contains filter operator for Integers?
e.g. object1 has id:1234. If I query 123 then it should return object1. The only filter available for Integers that comes close is equalTo but for this to work I would have to pass 1234 to the query.
Probably you need to add helper field that represent your id as String and query contains() based on this field.
You need to change your Integer field to String and then you can filter from Realm in this way
realm.where(YourRealmModel.class).contains("id","123").findAll()
It appears you're trying to access an object via it's a primary key of id. You can access that object directly with the following code without a query. Assuming we have a DogClass:
class DogClass: Object {
#objc dynamic var id = NSUUID().uuidString
#objc dynamic var dog_name = ""
override static func primaryKey() -> String? {
return "id"
}
}
let realm = try! Realm()
let primaryKey = 123
guard let thisDog = realm.object(ofType: DogClass.self, forPrimaryKey: primaryKey) else { return }
print(thisDog.dog_name)

Can I derive ARRAY_CONTAINS from query method name in Spring Data Couchbase Repository?

I have a Couchbase-Document "Group" with a list of group-members-names. I want to query for all groups of one person. I managed to do it with N1QL ARRAY_CONTAINS - see in code example - but i hoped that i could generate the query from the method name as it is usual in Spring Data.
Any help is appreciated :)
I tried
public List<MyGroup> findAllByMembers(String member); and public List<MyGroup> findByMembers(String member); but they just return an empty list - i guess they try to match the whole "members" value and don't recognize it as a list -, no errors.
Code
My Document with a List field
#Data
#Document
public class MyGroup {
private String name;
private List<String> members = new ArrayList<>();
}
My Repository
#RepositoryDefinition(domainClass = MyGroup.class, idClass = String.class)
public interface MyGroupRepository extends CouchbaseRepository<MyGroup, String> {
//#Query("#{#n1ql.selectEntity} WHERE ARRAY_CONTAINS(members,$1) AND #{#n1ql.filter}")
public List<MyGroup> findAllByMembers(String member);
}
Expected
Given a "group1" with "member1" in members.
repository.findAllByMembers("member1"); should return ["group1"].
Couchbase is limited by the Spring Data specification. Unfortunately, we can't simply add new behaviors to it (if you switch to a relational database, it has to work with no breaking points). So, whenever you need to query something that has a N1QL specific function/keyword, you have to write a query via #Query

Criteria Api: Use another parameter in multiselect, if the first one is null

I have a POJO class person which has two field. Lets assume only one of them holds a value and the other one is always null
public class Person {
private String music;
private String sports;
...
}
I want to fill either the one or the other into a List of DTOs via Criteria Api.
Here is a snippet of my (incomplete) Dao Code:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<PersonDTO> query = cb.createQuery(PersonDTO.class);
Root<Person> root= query.from(Person.class);
Path<String> musicPath = root.get(Person_.music);
Path<String> sportsPath= root.get(Person_.sports);
query.multiselect(/** TODO */);
List<PersonDTO> results = em.createQuery(query).getResultList();
Is there a way to use either music oder sports for the multiselect, depending on which of them is NOT null for the current record.
Or do i have to define a subquery to achieve this behavior?
You are looking for the COALESCE expression (see Ch. "Query Language", paragraph "Case Expressions" in the specification).
Create an expression that returns null if all its arguments evaluate to null, and the value of the first non-null argument otherwise.
The corresponding criteria API are the CriteriaBuilder.coalesce() set of methods. Selecting a single string is something as simple as:
query.select(cb.coalesce(musicPath, sportsPath));
If you want a PersonDTO of course, you will have to make use of the CriteriaBuilder.construct() method and an appropriate constructor:
query.select(cb.construct(PersonDTO.class, cb.coalesce(musicPath, sportsPath), ...));

querying and converting a neo4j query result to multi dimensional #QueryResult object

I have a #QueryResult interface, which itself declares a getter method that returns a list of objects of the same type. I wonder if there is a way to convert a neo4j query result to a proxied object that implements this domain interface ?
Here is the interface of the domain I tried for testing, which did not work:
#QueryResult
public interface Test
{
#ResultColumn( "id" )
public String getId();
#ResultColumn( "name" )
public String getName();
#ResultColumn( "tests" );
java.util.Collection<Test> getTests();
}
I used neo4Template#query( String, Map) to convert the query below to a proxied object that implements the above interface
MATCH (n:Label {id:{id}) WITH n MATCH (n)-[:INCLUDES]->(s) with n, s, COLLECT ({id:s.id, name:s.name}) AS tests RETURN n.name as name, n.id as id, tests
However, I got this exception:
Expexted a column named toString to be in the result set.
at
org.springframework.data.neo4j.support.conversion.ResultColumnValueExtractor.extractFromAccessibleObject(ResultColumnValueExtractor.java:74)
at org.springframework.data.neo4j.support.conversion.ResultColumnValueExtractor.extractFromMethod(ResultColumnValueExtractor.java:56)
at org.springframework.data.neo4j.support.conversion.QueryResultProxy.invoke(QueryResultProxy.java:54)
at com.sun.proxy.$Proxy173.toString(Unknown Source)
at java.lang.String.valueOf(String.java:2854)
at java.lang.StringBuilder.append(StringBuilder.java:128)
at org.neo4j.helpers.collection.IteratorUtil.single(IteratorUtil.java:338)
at org.neo4j.helpers.collection.IteratorUtil.singleOrNull(IteratorUtil.java:128)
at org.neo4j.helpers.collection.IteratorUtil.singleOrNull(IteratorUtil.java:286)
at org.springframework.data.neo4j.conversion.QueryResultBuilder.singleOrNull(QueryResultBuilder.java:71)
Does anyone know if this is possible to achieve using spring data neo4j? Thanks for your help

Use SELECT NEW CONSTRUCTOR with parameter not from tables

I'm using something like this now in my HQL:
"SELECT NEW com.somepackage.dto.SomeClass(myObj) "
But now I want to add a boolean parameter to constructor.
I've added it to my DAO method with HQL and to constructor of my dto object:
"SELECT NEW com.somepackage.dto.SomeClass(myObj, :param) "
...
.setParameter("param", param)
After adding parameter I got an exception:
Unable to locate appropriate constructor on class
Is there a way to add param to constructor? Or I was made something wrong?
Thx for your replies and sorry for my English.
Update
(Simple copy of my SomeClass):
public class SomeClass extends SomeClassParent {
private final String someParam;
private final List<MyObject> myObjects;
public SomeClass(MyObject myObject) {
super(myObject.getFirstField,
myObject.getSecondField, ...);
this.someParam = myObject.getSomeParamValue();
StringBuilder bodyBuilder = new StringBuilder();
...
I want it to be
public SomeClass(MyObject myObject, boolean myBoolean) {
I don't know exactly what was the problem with boolean, but now I'm using String parameter against boolean and use it like this:
"SELECT NEW com.somepackage.dto.SomeClass(myObj, '" + param + "') "...
setParameter doesn't want to work with String, because it requires quotes to be result string like this:
"SELECT NEW com.somepackage.dto.SomeClass(myObj, 'Some string') "...
against
"SELECT NEW com.somepackage.dto.SomeClass(myObj, Some string) "...
Ok, what it wasn't clear to me was if you had the SomeClass definition, you can define as many constructors as you want as long as they have different types, or quantities of parameters passed by.
It can be see as a kind of override (although it is not!)
It's up to you to define it, and do whatever you want with that Boolean, in fact you can copy and paste the original constructor (just leave that one there, don't erase it) with the Boolean's addition and it would be as valid as the previous one.
I'm pretty sure that your problem is with the boolean field. I worked with Hibernate HQL and I had a similar problem with a field. At the end I realized that I have to use nullable files for every field.
So, I think this problem could be solved turning boolean primitive field into Boolean Object class.
I'm having a similar problem with constructing a result entity using a query parameter as a constructor argument - like "select new com.example.ResultType(t.id, ?1) from Table t where ...". It seems such bare query params just get ignored when looking for constructors - in that example it would look for a constructor that takes a single argument matching t.id.
The only work-around I've found so far is to wrap the parameter with a cast (or some other non-trivial expression), e.g. "select new com.example.ResultType(t.id, cast(?1 as string)) ...".

Categories

Resources