I have a repository looking like this (with other CRUD methods stripped)
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.StringPath;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.lang.NonNull;
import org.springframework.security.access.prepost.PreAuthorize;
import java.util.Optional;
import java.util.UUID;
#PreAuthorize("hasRole('" + Constants.ROLE_USER + "')")
public interface ProjectRepository extends CrudRepository<Project, UUID>, QuerydslPredicateExecutor<Project>, QuerydslBinderCustomizer<QProject> {
#Override
default void customize(#NonNull QuerydslBindings bindings, #NonNull QProject root) {
bindings.bind(String.class).first(
(StringPath path, String value) -> path.containsIgnoreCase(value));
bindings.including(root.name);
bindings.including(root.description);
}
#Override
#Query("select p from Project p left join p.roles r left join r.account a where ?#{principal.username} = a.username")
#NonNull
Page<Project> findAll(#NonNull Predicate predicate, #NonNull Pageable pageable);
}
As you can see I have a #Query annotation that limits the response of findAll based on who the user is. This causes the Predicate to be ignored entirely. So if I search for anything, it still returns all objects the user has access to. If I remove the #Query annotation then the searching works correctly. But of course I want my security to be applied. Is this a bug in QueryDsl? Or simply a limitation? How could I make this work?
Related
I am attempting to use Java records with #Valid and #RequestBean in Micronaut and am running into the following compilation error:
/Users/user/IdeaProjects/record_test/src/main/java/com/example/ReadController.java:16:28
java: Parameter of Primary Constructor (or #Creator Method) [id] for type [com.example.ReadBean] has one of #Bindable annotations. This is not supported.
Note1: Primary constructor is a constructor that have parameters or is annotated with #Creator.
Note2: In case you have multiple #Creator constructors, first is used as primary constructor.
My classes are as follows:
ReadBean.java:
package com.example;
import io.micronaut.core.annotation.Introspected;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.annotation.PathVariable;
import javax.validation.constraints.Positive;
#Introspected
public record ReadBean(HttpRequest<?> httpRequest, #PathVariable #Nullable #Positive Integer id) {
}
ReadController.java:
package com.example;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;
import io.micronaut.http.annotation.RequestBean;
import javax.validation.Valid;
#Controller("/api/read")
public class ReadController {
#Get
#Produces(MediaType.APPLICATION_JSON)
public HttpResponse<?> read(#Valid #RequestBean ReadBean bean) {
return HttpResponse.ok(bean);
} //read
}
This error appears to be due to my use of #PathVariable. I can get around this error by explicitly declaring the canonical constructor in my record:
package com.example;
import io.micronaut.core.annotation.Introspected;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.annotation.PathVariable;
import javax.validation.constraints.Positive;
#Introspected
public record ReadBean(HttpRequest<?> httpRequest, #PathVariable #Nullable #Positive Integer id) {
public ReadBean(HttpRequest<?> httpRequest, Integer id) {
this.httpRequest = httpRequest;
this.id = id;
} //ReadBean
}
Is there any cleaner way to get around this? I recall that annotations on record components are propagated to the associated fields, constructors, etc. It would just be nice to not have to declare the constructor explicitly.
Thanks!
**please help i have placed hidden inside package and import something else is there please mind the change **
package hidden;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import hidden;
public interface SubscriberIdDetailsRepository extends JpaRepository<SubscriberIdDetails, Integer> {
#Query("Select count(distinct s.msisdn) from subscriber_details s where s.subscriber_details_id in (select d.subscriber_details_id from subscriber_id_details d where d.UPPER(REGEXP_REPLACE(id_number,'[^[:alnum:]'' '']', ''))=:idNumber")
Integer countByidNumber( #Param("idNumber") String idNumber);
}
Your query is calling REGEXP_REPLACE, which is a database-specific string function. It won't run as pure JPQL, so you will have to pass nativeQuery=true to the end of #Query to mark it as a native query.
public interface SubscriberIdDetailsRepository extends JpaRepository<SubscriberIdDetails, Integer> {
#Query(value = "SELECT COUNT(DISTINCT s.msisdn) FROM subscriber_details s WHERE s.subscriber_details_id IN (SELECT d.subscriber_details_id FROM subscriber_id_details d WHERE d.UPPER(REGEXP_REPLACE(id_number,'[^[:alnum:]'' '']', '')) = :idNumber",
nativeQuery = true
)
Integer countByidNumber(#Param("idNumber") String idNumber);
}
Im devloping a crud application in spring-boot and i was wondering if i can do these two queries and methods in one:
package com.celulaweb.crud.repository;
import com.celulaweb.crud.domain.Cidade;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
#Repository
public interface CidadeRepository extends JpaRepository<Cidade, Long> {
#Query("select c from Cidade c where c.estado is null or c.estado = :estado")
Page<Cidade> listarPorEstado(#Param("estado") String estado, Pageable pageable);
#Query("select c from Cidade c where c.nome is null or c.nome like :nome")
Page<Cidade> listarPorNomeTendo(#Param("nome") String nome, Pageable pageable);
}
These are queries from org.springframework.data.jpa.repository.Query
How can i merge these two?
If you have the same Pageable on this methods try this
#Query("""
select c from Cidade c
where (c.estado is null or (c.estado = :estado))
and (c.nome is null or (c.nome like :nome))
"""
)
Page<Cidade> listarEntries(
#Param("estado") estado: String,
#Param("nome") nome: String,
pageable: Pageable
)
i have a class called "Invoice" and a MongoRepository
and what i want is to extract from my mongo database all validated invoices (those created in a given time range)
so here is my mongo repository :
import java.util.Date;
import java.util.List;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import Invoices.Invoice;
#Repository
public interface InvoiceRepositoryMongo extends MongoRepository<Invoice,Integer>{
#Query("db.invoices_bis.find({createdAt : {$gte : new ISODate('2013-04-30T17:24:16.000+00:00') , $lte : new ISODate('2013-05-30T17:24:16.000+00:00')}})")
List<Document> testrequete(Date start, Date ed);
}
dont pay too much attention to the query it is just for testing , but the problem is when i run this , i have this error :
nested exception is org.springframework.data.mapping.PropertyReferenceException: No property testrequete found for type Invoice!
i think the problem is that the method return a list of but i'm not sure
thanks !
i think te problem is that your Entity calls Invoice,
MongoRepository<Invoice,Integer>
so the result should be something like :
List<Invoice> testrequete(Date start, Date ed);
I'm new in Spring. I want to create a repository that return Page of object array like this:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface A extends JpaRepository<Object, Long> {
#Query("SELECT a, b FROM EntityA a FULL OUTER JOIN EntityB b ON "
+ "a.id = b.id")
Page<Object[]> findAll(Pageable pageable);
}
But I get:
nested exception is java.lang.IllegalArgumentException: Not an managed type: class java.lang.Object
Thank you