Multiple "And/Or" Condition Expressions spring data jpa [duplicate] - java

This question already has answers here:
Spring data jpa - How to combine multiple And and Or through method name
(4 answers)
Closed 7 days ago.
I want to have a filter query using spring data JPA.
condition is something like this:
(A or B or C) and D
when I want to use Spring Data JPA I should change it to be like below (The precedence order is And then Or, just like Java.):
(A and D) or (B and D) or (C and D)
the code in the Spring Repository class is:
Page<SystemEntity>  findByNameContainsAndFlagIsFalseOrFamilyContainsAndFlagIsFalseOrEmailContainsAndFlagIsFalse(String name, String family ,String email, Pageable pageable);
you can see that the D condition at the above line "AndFlagIsFalse" is repeated 3 times.
is there any way to implement using a shorter format like "(A or B or C) and D"?

Using the #Query annotation you can define the query directly:
#Query("SELECT se FROM SystemEntity se WHERE (se.name = :name AND se.flag = true) OR (. . .) OR (. . .)")
Page<SystemEntity> findSystemEntities(String name, String family ,String email, Pageable pageable);

Related

JPA Multple Query using AND/OR Precedence [duplicate]

I am trying to migrate the application. I am working on from Hibernate to Spring Data Jpa.
Though spring data jpa offers simple methods for query building, I am stuck up in creating query method that uses both And and Or operator.
MethodName - findByPlan_PlanTypeInAndSetupStepIsNullOrStepupStepIs(...)
When it converts into the query, the first two expressions are combined and it executes as [(exp1 and exp2) or (exp3)].
whereas required is ](exp1) and (exp2 or exp3)].
Can anyone please let me know if this is achievable through Spring data jpa?
Agree with Oliver on long and unreadable method names, but nevertheless and for the sake of argument, you can achieve desired result by using the equivalency
A /\ (B \/ C) <=> (A /\ B) \/ (A /\ C)
A and (B or C) <=> (A and B) or (A and C)
So in your case it should look something like this:
findByPlan_PlanTypeInAndSetupStepIsNullOrPlan_PlanTypeInAndStepupStepIs(...)
It's currently not possible and also won't be in the future. I'd argue that even if it was possible, with a more complex query you wouldn't want to artificially squeeze all query complexity into the method name. Not only because it becomes hard to digest what's actually going on in the query but also from a client code point of view: you want to use expressive method names, which — in case of a simple findByUsername(…) — the query derivation allows you to create.
For more complex stuff you' just elevate query complexity into the calling code and it's advisable to rather move to a readable method name that semantically expresses what the query does and keep the query complexity in a manually declared query either using #Query, named queries or the like.
Use something like
findByFirstElementAndCriteriaOrSecondElementAndCriteria
is like (first & condition) OR ( second & condition) --> condition & ( first or second)
Option1: You could use named-queries (see Using JPA Named Queries):
#Entity
#NamedQuery(name = "User.findByEmailAddress",
query = "select u from User u where u.emailAddress = ?1")
public class User {
}
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmailAddress(String emailAddress);
}
Option2: use #Query to write your custom queries (see Using #Query)
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}

Is there any way to use table name from #params in #query annotation in Hibernate? [duplicate]

This question already has answers here:
How to replace table name with parameter value while using Spring Data JPA nativeQuery
(5 answers)
Closed 3 years ago.
I am using Hibernate and Spring data JPA to build a web project.
In Eclipse-Link we can use native query like
String tableName = "sometablename";
String query = "SELECT * FROM " +tableName +"WHERE id > 10";
In Hibernate I am using #Query annotation
#Query(value = "SELECT COUNT(r.id) as resultsCount FROM #{#resultTable} r WHERE r.customerId= :customerId AND r.is_deleted=0 AND r.is_ignored=0 ", nativeQuery = true)
Integer getResultsCount(#Param("customerId") int customerId,
#Param("resultTable") String resultTable);
I tried #{#resultTable} but this is getting replaced as a string with quote and i am getting an exception that
You have a error in your SQL Syntax
I want to use table name dynamically from params. Is it possible? And if yes, Please tell me how?
It's not possible, #org.springframework.data.jpa.repository.Query takes only jpql, you cannot pass the name of the table since it's not recognized as any entity.
It states the javadoc of Query:
/**
* Defines the JPA query to be executed when the annotated method is called.
*/
String value() default "";
The best solution would be not to pass tablename as string, but resolve it using for example inheritance (link) or rebuild your datamodel somehow. As a quick and dirty solution I would suggest creating a custom repository and using EntityManager.createNativeQuery and pass the sql there. But remember to validate the query you're composing (validate user input, use enums for table names), because it can lead to sql injection.
Your own observations actually answer your question:
I tried #{#resultTable} but this is getting replaced as a string with quote and i am getting an exception
The placeholders which are used inside the #Query query string are intended to filled with literal values. Hence, the table name ended up appearing as literal string, inside single quotes. This means that behind the scenes #Query and Spring are probably using a JDBC prepared statement. It is not possible to bind the name of the table. Allowing this would be a major security hole.
The only possible workaround here would be to concatenate your query string together, and then trying to use that string with #Query. But note that this would not be a safe option.
What you are doing is wrong, you are mixing business logic into DAO layer, i suggest you create two DAO's, each one with its own table and query, then into the business/service layer call the desired one.

Is there a query that returns table content with partial information in the search box? [for #Query annotation] [duplicate]

This question already has answers here:
Spring JPA #Query with LIKE
(12 answers)
Closed 3 years ago.
This is my query
#Query(value = "SELECT * FROM STUDENT WHERE first_name =?1", nativeQuery = true)
public List<Student> searchStudents(String searchName);
So now when I search a student I need to give the full first name or else it returns null... Here is my Student service.. basically returning a list, and this is the method I call in my UIController..
return studentRepository.searchStudents(searchName);
If there is not a statement in the #Query annotation, how can I search with just a few letters of the word and get words containing those letters?
Thanks!
Use the LIKE operator (see doc)
Using Spring JPA you can do this using the method signature:
List<Student> findByFirstnameLike(String name);
More details: https://stackoverflow.com/a/38115592/4325878

Spring data jpa - How to combine multiple And and Or through method name

I am trying to migrate the application. I am working on from Hibernate to Spring Data Jpa.
Though spring data jpa offers simple methods for query building, I am stuck up in creating query method that uses both And and Or operator.
MethodName - findByPlan_PlanTypeInAndSetupStepIsNullOrStepupStepIs(...)
When it converts into the query, the first two expressions are combined and it executes as [(exp1 and exp2) or (exp3)].
whereas required is ](exp1) and (exp2 or exp3)].
Can anyone please let me know if this is achievable through Spring data jpa?
Agree with Oliver on long and unreadable method names, but nevertheless and for the sake of argument, you can achieve desired result by using the equivalency
A /\ (B \/ C) <=> (A /\ B) \/ (A /\ C)
A and (B or C) <=> (A and B) or (A and C)
So in your case it should look something like this:
findByPlan_PlanTypeInAndSetupStepIsNullOrPlan_PlanTypeInAndStepupStepIs(...)
It's currently not possible and also won't be in the future. I'd argue that even if it was possible, with a more complex query you wouldn't want to artificially squeeze all query complexity into the method name. Not only because it becomes hard to digest what's actually going on in the query but also from a client code point of view: you want to use expressive method names, which — in case of a simple findByUsername(…) — the query derivation allows you to create.
For more complex stuff you' just elevate query complexity into the calling code and it's advisable to rather move to a readable method name that semantically expresses what the query does and keep the query complexity in a manually declared query either using #Query, named queries or the like.
Use something like
findByFirstElementAndCriteriaOrSecondElementAndCriteria
is like (first & condition) OR ( second & condition) --> condition & ( first or second)
Option1: You could use named-queries (see Using JPA Named Queries):
#Entity
#NamedQuery(name = "User.findByEmailAddress",
query = "select u from User u where u.emailAddress = ?1")
public class User {
}
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmailAddress(String emailAddress);
}
Option2: use #Query to write your custom queries (see Using #Query)
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}

Spring Data JPA / OpenJPA: Is there an equivalent to SQL !=-Operator

Is there an equivalent to the native sql !=-operator for Spring Data JPA #Query-Annotation using OpenJPA? So i thought it would work somewhat like this:
#Query("select a from TableA a, TableB b where a.property != b.property")
but it doesn't, or lets say at least my ide (intellij) shows me that it does not know how to work with '!='.
The (as i thought) corresponding
#Query("select a from TableA, TableB b where a.property = b.property")
works.
In JPQL you should use SQL syntax (for the most part) meaning that != is expressed with <>. See also this wiki article

Categories