how to write predicate for QueryDslPredicateExecutor - spring

When i try to use Querydsl as shown in Spring reference Spring 1.10.4.RELEASE reference - i get some errors from IDE:
Cannot resolve method findAll(predicate). I changed import to com.mysema.query.types.Predicate. Now method looks fine.
But i cant resolve problem with:
Predicate predicate = user.getUsername().equalsIgnoreCase(username).and((user.getId().equals(userid)).not);
I got errors: cannot resolve method: and, cannot resolve method not.
Some from reference:
Example 32. Querydsl integration on repositories
interface UserRepository extends CrudRepository<User, Long>, QueryDslPredicateExecutor<User> {
}
The above enables to write typesafe queries using Querydsl Predicate s.
Predicate predicate = user.firstname.equalsIgnoreCase("dave")
.and(user.lastname.startsWithIgnoreCase("mathews"));
userRepository.findAll(predicate);
But example is incorrect.
Anybody know how to use this?

You are probably using the wrong user object to start with. I assume you are currently using your domain class User but you need to use the class generated by Querydsl, normally named QUser.
See https://github.com/querydsl/querydsl/tree/master/querydsl-jpa for example code.
See QueryDsl - How to create Q classes with maven? for how to generate the necessary classes with Querydsl.

Related

Spring finds a test class on a jar and I get a NoUniqueBeanDefinitionException

I have a project that uses Spring. The project consists on two different parts, the generic part and the specific one. The generic part is compiled as a .jar, it defines a set of traits and it's used as a dependency by the specific part, which is the one that implements the methods.
In order to test the generic part, I have created a "fake" implementation of one of the trait (let's say "fakeMethodA"), under the test directory of the generic project and I annotated this fake implementation with the #Component annotation. I'm getting the beans using the application context.
The problem comes when I try to use this generic part on the specific project. Since my actual implementation of this trait (let's say "methodAImplementation") also has a #Component annotation, when I run my tests I get:
org.springframework.beans.factory.NoUniqueBeanDefinitionException
expected single matching bean but found 2:
It finds the fakeMethodA from the generic part and methodAImplementation from the implementation. Is there any way to exclude this "fake" implementation from the execution? Is there a better way to define this?
Any help would be greatly appreciated.
The problem was solved by the use of #Profile annotation on the generic method.
I annotated the fake method on the tests with:
#Profile(value = Array("Test"))
And the right implementation with another profile value. After that, when I select the bean from the context, I can select the correct profile.

List<List<String>> mapped to List<String>

I'm learning how to use Mapstruct in a Spring Boot and Kotlin project.
I've got a generated DTO (ThessaurusDTO) that has a List and I need this mapped into a List on my model (Vocab).
It makes sense that MapStruct can't map this automatically, but I know for a fact that the first list will always be size = 1. I have no control on the API the DTO model belongs to.
I found on the documentation that I can create define a default method implementation within the interface, which would loosely translate to a normal function in Kotlin
My mapper interface:
#Mapper
interface VocabMapper {
#Mappings(
// ...
)
fun thessaurusToVocab(thessaurusDTO: ThessaurusDTO): Vocab
fun metaSyns(nestedList: List<List<String>>): List<String>
= nestedList.flatten()
}
When I try to do a build I get the following error:
VocabMapper.java:16: error: Can't map collection element "java.util.List<java.lang.String>" to "java.lang.String ". Consider to declare/implement a mapping method: "java.lang.String map(java.util.List<java.lang.String> value)".
It looks like mapStruct is still trying to automatically do the mapping while ignoring my custom implementation. Am I missing something trivial here?
I found on the documentation that I can create define a default method implementation within the interface, which would loosely translate to a normal function in Kotlin
From my understand of what I found online, Kotlin does not properly translate an interface function into a default method in Java, but actually generates a class that implements the interface.
If that's the problem, you can annotate metaSyns with #JvmDefault:
Specifies that a JVM default method should be generated for non-abstract Kotlin interface member.
Usages of this annotation require an explicit compilation argument to be specified: either -Xjvm-default=enable or -Xjvm-default=compatibility.
See the link for the difference, but you probably need -Xjvm-default=enable.
I've seen to have fixed this by relying on an abstract based implementation, instead of using an interface.
From my understand of what I found online, Kotlin does not properly translate an interface function into a default method in Java, but actually generates a class that implements the interface.
https://github.com/mapstruct/mapstruct/issues/1577

Spring inject list of generic interface implementations in kotlin

Disclaimer: New to Kotlin, may be a easy to solve issue or misunderstood basics.
I am trying to inject a List of a specific interface's Spring implementations, in a regular java class this have been easy like this:
#Autowired
List<IMyClass> myClassList;
But in Kotlin doing the following gives me a error
#Autowired
lateinit private var myClassList: List<IMyClass<Any>>
// No beans of '? extends IMyClass<Object>' or 'List<? extends IMyClass<Object>>' types found
Doing it like this:
#Autowired
lateinit private var myClassList: List<IMyClass<*>>
Makes the injection work but doesn't allow me to use a function defined in the interface that takes a generic object as input
// Out-projected type 'IMyClass<*>' prohibits the use of 'public abstract fun myFunction(obj: T!): T! defined in com.path.IMyClass'
So how am I supposed to solve this? Is it easier to rewrite the interface in Kotlin with some specific syntac?
Thing you're doing in Java is just using implicit wildcard. So you have 2 ways here:
Try to refactor API and inject list of List<IMyClass<? extends SomeInterface>>
Use injected List<IMyClass<*>> but cast it explicitly to thing you need, i.e. myClassList as List<IMyClass<Any>>
Thing here is kotlin's erasure is more explicit. If you don't know what type is there — we can't guarantee your code will work, because there is such type in kotlin as Nothing, instance of which can't exist.
I faced a similar situation and as answered by asm0dey, casting was solution which I felt was better for me, but doing it in a cleaner way was a concern.
Just answering below how exactly I did it in the best possible way that I could think of:
#Service
class MyService(_myClassList: List<IMyClass<out Any>>) {
#Suppress("UNCHECKED_CAST")
val myClassList: List<IMyClass<Any>> = _myClassList.map { it as IMyClass<Any> }
// ...
}

Spring Data MongoDB: Specifying a hint on a Spring Data Repository find method

I am implementing a Spring Data Repository and having my repository extend the MongoRepository. I am looking for a way to specify a hint on my findBy methods so I can be control. I have seen several times when a non-optimal index would be picked as the winning plan.
This is what my repository looks like right now:
public interface AccountRepository extends MongoRepository<Account, ObjectId> {
#Meta(maxExcecutionTime = 60000L, comment = "Comment" )
public List<Account> findByUserIdAndBrandId(Long userId, Long brandId);
}
I researched a bunch and found that the JPARepository from spring data supports the #QueryHint annotation but I do not believe that annotation is supported for MongoDb. Is there a similar annotation I can specify on top of my findBy method to specify the hint?
MongoTemplate allows to specify a hint, however, I have a ton of findBy methods and I would hate to add an implementation underneath just to specify a hint.

Limit findAll possible with Spring?

Is it possible with Springs auto implemented repositories to limit the result size of the findAll method?
I'm trying to have something like the following declared in the interface:
List<XY> findAllTopTen();
Unfortunatelly, it doesn't work (this) way...
If you dont have a Pageable object that came from your controller and just need to get X amount of objects from DB, you can do the following:
First, your Repository class has to extend JpaRepository<T, ID> so it wil be able to query using a Pageable object.
Second, you can define a Pageable object this way:
Pageable limit = PageRequest.of(0,10);
return repository.findall(limit);
In this case, the query would return the first 10 objects.
You can find more info here (Scroll down to 4.1, Example 4)
Note that the example actually extends PagingAndSortingRepository but JpaRepository contains all the methods from PagingAndSortingRepository and has additional functions aswell.
Edit: Thanks to #Zunnii for pointing out that new PageRequest() is now deprecated. I edited the snippet above to reflect that.
Pass a Pageable as a parameter like following:
Page<x> findAll(Pageable pageable);
You need to explicitly specify the ordering, otherwise Spring Data JPA has no way of deciding what criteria it should use. For instance:
List<XY> findAllTopTenByAge();
See more details in the official documentation.

Resources