Dynamic spring data jpa repository query with arbitrary AND clauses
Please note that there might be changes to be done to use the new major version of QueryDSL (4.x) and querydsl-jpa
In one of our projects, we used QueryDSL
with QueryDslPredicateExecutor<T>
.
public Predicate createPredicate(DataEntity dataEntity) {
QDataEntity qDataEntity = QDataEntity.dataEntity;
BooleanBuilder booleanBuilder = new BooleanBuilder();
if (!StringUtils.isEmpty(dataEntity.getCnsiConsumerNo())) {
booleanBuilder
.or(qDataEntity.cnsiConsumerNo.contains(dataEntity.getCnsiConsumerNo()));
}
if (!StringUtils.isEmpty(dataEntity.getCnsiMeterNo())) {
booleanBuilder.or(qDataEntity.cnsiMeterNo.contains(dataEntity.getCnsiMeterNo()));
}
return booleanBuilder.getValue();
}
And we could use this in the repositories:
@Repository
public interface DataEntityRepository
extends DaoRepository<DataEntity, Long> {
Where DaoRepository
is
@NoRepositoryBean
public interface DaoRepository<T, K extends Serializable>
extends JpaRepository<T, K>,
QueryDslPredicateExecutor<T> {
}
Because then, you can use repository predicate methods.
Iterable<DataEntity> results = dataEntityRepository.findAll(dataEntityPredicateCreator.createPredicate(dataEntity));
To get QClasses
, you need to specify the QueryDSL APT Maven plugin in your pom.xml.
<build>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>maven-apt-plugin</artifactId>
<version>1.0.4</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources</outputDirectory>
<processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
Dependencies are
<!-- querydsl -->
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-core</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
Or for Gradle:
sourceSets {
generated
}
sourceSets.generated.java.srcDirs = ['src/main/generated']
configurations {
querydslapt
}
dependencies {
// other deps ....
compile "com.mysema.querydsl:querydsl-jpa:3.6.3"
compile "com.mysema.querydsl:querydsl-apt:3.6.3:jpa"
}
task generateQueryDSL(type: JavaCompile, group: 'build', description: 'Generates the QueryDSL query types') {
source = sourceSets.main.java
classpath = configurations.compile + configurations.querydslapt
options.compilerArgs = [
"-proc:only",
"-processor", "com.mysema.query.apt.jpa.JPAAnnotationProcessor"
]
destinationDir = sourceSets.generated.java.srcDirs.iterator().next()
}
compileJava {
dependsOn generateQueryDSL
source generateQueryDSL.destinationDir
}
compileGeneratedJava {
dependsOn generateQueryDSL
classpath += sourceSets.main.runtimeClasspath
}
Dynamic query using JpaRepository
I'm posting the solution here.
I didn't use the JPARepository
, I added the treatment of my request in the ServiceImpl
, directly injecting the EntityManager
in this way:
an example taking as filter just unidad (i can add others)
public class PeticionServiceImpl implements PeticionService {
/*..
*/
@Inject
private EntityManager em;
@Override
public List<PeticionDTO> searchFilter( String unidad) {
String consulta = "select peticion from Peticion peticion ";
if (unidad != null && !"".equals(unidad)) {
consulta = consulta + " where ";
if (unidad != null && !"".equals(unidad)) {
consulta = consulta
+ " UPPER(translate(peticion.contacto.poa, 'áéíóúÁÉÍÓÚ', 'aeiouAEIOU')) LIKE UPPER(translate('%"
+ unidad + "%', 'áéíóúÁÉÍÓÚ', 'aeiouAEIOU')) ";
filtro = true;
}
}
peticiones = peticionMapper.peticionsToPeticionDTOs((List<Peticion>) em.createQuery(consulta).getResultList());
return peticiones;
}
}
Spring Data JPA: How to form a conditional query?
For optional field, use this : @Query("select d from data d where (:name is null or d.name=:name) and (:age is null or d.age=:age) and (:date is null or d.date=:date)")
Related Topics
How to Calculate "Time Ago" in Java
Java Integer Compareto() - Why Use Comparison VS. Subtraction
Concurrent Modification Exception
How to Resolve Java Unknownhostkey, While Using Jsch Sftp Library
Setting Background Images in Jframe
Should a Retrieval Method Return 'Null' or Throw an Exception When It Can't Produce the Return Value
Why Should I Use the Keyword "Final" on a Method Parameter in Java
Can Overridden Methods Differ in Return Type
How to Fix Org.Hibernate.Lazyinitializationexception - Could Not Initialize Proxy - No Session
Output in a Table Format in Java's System.Out
Is a Java Hashmap Search Really O(1)
How Does Cloneable Work in Java and How to Use It
Split String into Array of Character Strings