I need to lowercase all emails when querying my table, but the documentation specifies only method-name-keyowrd for UPPER():
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)
How the LOWER() could be used?
I have debug it and can see that PredicateBuilder doesn't seem to be considering it.
Are you aware if that is a limitation? Or could this be achieved in different way?
As per the Spring JPA reference guide, findXXXByIgnoreCase(...) by default uses UPPER(...) to perform case insensitive search.
To force it to use LOWER keyword we can use a custom query with #Query annotation and specifying SELECT .... LOWER(email)= LOWER(?1).
In my case I have used custom query as below to force it to use LOWER keyword for email column:
#Query("SELECT p from Person p where LOWER(email) = LOWER(?1)")
List<Person> findByEmailIgnoreCase(#Param("email") String email);
and this resulted in creating following query:
Hibernate: select person0_.id as id1_0_, person0_.email as email2_0_, person0_.first_name as first_na3_0_, person0_.last_name as last_nam4_0_ from person person0_ where lower(person0_.email)=lower(?)
This should help the query to use the function index i.e., LOWER(email).
The Spring Data JPA docs say this about case sensitivy of properties:
// Enabling ignoring case for an individual property
List<Person> findByLastnameIgnoreCase(String lastname);
// Enabling ignoring case for all suitable properties
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
Using IgnoreCase in your method name will automatically generate a query which is case insensitiv for one or all specified properties.
Otherwise you always have the possibility to specify a custom query for your method by annotating it like this:
#Query("select u from User u")
Stream<User> findAllByCustomQueryAndStream();
By using the #Query annotation you can use the plain old JPQL to query your database.
Related
I have an HQL query that takes msisdn and subServiceId on an Entity Unsubscription.
Below is the code for the same:
Query query = session.createSQLQuery(unsubscriptionInfodemo)
.addEntity(Unsubscription.class)
.setParameter("msisdn", msisdn)
.setParameter("subServiceId", subServiceId);
Now,I need to check in this Unsubscription entity whether subServiceId is the subServiceId I have passed or it should be the subServiceId I have hardCoded.
Can I apply like
public void checkUser(String msisdn,String subServiceID){
Query query = session.createSQLQuery(unsubscriptionInfodemo)
.addEntity(Unsubscription.class)
.setParameter("msisdn", msisdn)
.setParameter("subServiceId", subServiceId)
.setParameter("subServiceId", "XYZ");
}
HQL query:
unsubscriptionInfodemo=select * from unsubscription s where s.msisdn=:msisdn and s.subservice_id=:subServiceId
Can anyone guide me how to proceed?
How to apply OR Condition in HQL?
use OR on your query:
select * from unsubscription s where s.msisdn=:msisdn and s.subservice_id=:subServiceId OR
s.subservice_id=:subServiceId2
and name parameters shouldn't be the same:
.setParameter("msisdn", msisdn)
.setParameter("subServiceId", subServiceId)
.setParameter("subServiceId2", "XYZ"); // Make this subServiceId2
The dynamic functionality you want to implement cannot be done with hql without changing the hql string.
I would consider using the criteria api which provides a dynamic functionality.
The easiest way is to either create the hql string based on the value (if subServiceId is existent or not) or use the criteria api, thus you will just have to add one extra equals filter in case of subServiceId presence.
The question should be changed on how to add dynamic conditions to hql based on variable presence.
Also check this answer
I've been trying to figure out how to take an input of a list of enums for my sql query. This is what it looks like:
#Query(value = "Select * from employees where city in :cities", nativeQuery = true)
List<Employee> findByCities(#Param("cities") List<City> cities);
I understand that for simple queries we can rely on the JPA Criteria API but I want to know if I can actually do it this way instead. Because if so, i can create more complicated queries (such as joins with another table) if I could have this flexibility of specifying the list.
Yes spring-data-jpa's #Query can take a list of enums.
This is my repository method
#Query("Select u from User u where u.userType in :types")
List<User> findByType(#Param("types") List<UserType> types);
This is my repository call
userRepository.findByType(Arrays.asList(AppConstant.UserType.PRINCIPLE)))
And this is the query logs
SELECT user0_.id AS id1_12_,
user0_.date_created AS date_created2_12_,
...
...
FROM users user0_
WHERE user0_.user_type IN ( ? )
Hope this helps.
PS: I tested this in my local machine with positive results.
Update 1
The same doesn't work with nativeQuery=true. I tested it on my local system and it doesn't seem to be working with native queries. However with JPQL it works fine as mentioned in the above answer.
May be this answer will help.
I have a 'Role' table with a 'name' column. I need to get all roles where names are either 'role1' or 'role2'. Role repository method looks like this:
Set<Role> findByNameIsIn(Set<String> roleNames);
My database contains only 'role1'. The request that is generated looks like this:
SELECT ID, NAME FROM ROLE WHERE (NAME IN ((?,?)))
bind => [role1, role2]
Please notice the double brackets around the parameters. Result set is empty. When I try this query manually through the h2 console - no results as well. The following query works:
SELECT ID, NAME FROM ROLE WHERE (NAME IN ('role1', 'role2'))
My set contains two elements exactly. Sets should be supported as a parameter type. See:https://dzone.com/refcardz/core-spring-data
And finally the question: What am I missing?
As Oliver Gierke mentioned - there is a bug opened for this issue in EclipseLink (this is what I'm using as a persistence provider) issue tracker. Since 2011!.. Here is the workaround:
#Query("select r from Role r where r.name in ?1")
Set<Role> findByNameIsIn(Set<String> roleNames);
And here is the valid generated query:
SELECT ID, NAME FROM ROLE WHERE (NAME IN (?,?))
bind => [role1, role2]
I would like to clarify few finding.
It's true when define Filter, it's required to define FilterDefs?
There's scenario that i does't required any parameter, because the filter it's self is sufficient.
eg: filterName="filter1" condition="ID in (select id from table1"), filterName="filter2" condition="ID in (select id from table2)"
It's true when define a Filter, filter name should not contain dot "." character?
When I define a class name as filterName, hibernate can't find FilterDefs
eg: filterName="org.my.company.Class1" condition="ID in (select id from table1")
Is the following condition is correct:
filterName="filter3" condition="ID in (select id from table1 where column1 like '%:param1%')"
question: What I'm tries to do?
Answer: I'm using Spring ACL and I want to query all granted entity for given sid. I had create Spring ACL entity object.
My domain and sid is my ACL session query parameter.
Then I'm using my domain name as a filter name so that a would easily enable the required filter
eg: session.enableFilter(myclass.getCanonicalName());
session.createQuery("select count(distinct aoi.id) from AclObjectIdentity aoi join aoi.entries e where ......"
Thanks
I have a query like below
select f.id, s.name, ss.name
from first f
left join second s on f.id = s.id
left join second ss on f.sId = ss.id
If I could use HQL, I would have used HQL constructor syntax to directly populate DTO with the result set.
But, since hibernate doesn't allow left join without having an association in place I have to use the Native SQL Query.
Currently I am looping through the result set in JDBC style and populating DTO objects.
Is there any simpler way to achieve it?
You could maybe use a result transformer. Quoting Hibernate 3.2: Transformers for HQL and SQL:
SQL Transformers
With native sql returning non-entity
beans or Map's is often more useful
instead of basic Object[]. With
result transformers that is now
possible.
List resultWithAliasedBean = s.createSQLQuery(
"SELECT st.name as studentName, co.description as courseDescription " +
"FROM Enrolment e " +
"INNER JOIN Student st on e.studentId=st.studentId " +
"INNER JOIN Course co on e.courseCode=co.courseCode")
.addScalar("studentName")
.addScalar("courseDescription")
.setResultTransformer( Transformers.aliasToBean(StudentDTO.class))
.list();
StudentDTO dto =(StudentDTO) resultWithAliasedBean.get(0);
Tip: the addScalar() calls were
required on HSQLDB to make it match a
property name since it returns column
names in all uppercase (e.g.
"STUDENTNAME"). This could also be
solved with a custom transformer that
search the property names instead of
using exact match - maybe we should
provide a fuzzyAliasToBean() method ;)
References
Hibernate Reference Guide
16.1.5. Returning non-managed entities
Hibernate's Blog
Hibernate 3.2: Transformers for HQL and SQL