Use Enum as parameter in Named Query - java

I have a named query that selects all the record that have a search string in it.
This is my NamedQuery.
#NamedQuery(
name = "findAllPersonBySearch",
query = "SELECT p FROM Person p "
+ "WHERE LOWER(p.pvId) LIKE LOWER(:searchString) "
+ "OR LOWER(p.firstName) LIKE LOWER(:searchString) "
+ "OR LOWER(p.middleName) LIKE LOWER(:searchString) "
+ "OR LOWER(p.lastName) LIKE LOWER(:searchString) "
+ "OR p.birthDate LIKE :searchString"
)
The record contains 2 enum in it. One is Gender and the Other is Person Type. Here are my enums:
PersonType
package ph.com.smesoft.hms.reference;
public enum PersonType {
Customer, Personnel
}
Gender
package ph.com.smesoft.hms.reference;
public enum Gender {
Male, Female
}
I have a search box in my list view which returns a string whenever the Search button is clicked.
How do I use the enums as parameters in my Named Query?
I have tried this:
ph.com.smesoft.hms.reference.PersonType.Personnel = :searchString
But nothing happened. Hope someone can help me out on this!
UPDATE:
This is where the method that accepts the string passed from the Controller and sets it as query parameter:
public List<Person> findAllBySearch(String searchString){
TypedQuery<Person> searchResult = em.createNamedQuery("findAllPersonBySearch", Person.class);
searchResult.setParameter("searchString",'%'+searchString+'%');
List<Person> result=searchResult.getResultList();
return result;
}
and this is my controller method that accepts the string typed from the view:
Controller Method
#RequestMapping(value = "/search", method = { RequestMethod.GET })
public String listofFloor(#ModelAttribute("SearchCriteria") SearchForm searchForm, Model uiModel) {
uiModel.addAttribute("people", personService.findAllBySearch(searchForm.getSearchString()));
return "people/list";
}

Related

spring boot query , what's wrong with this?

I'm trying to get data from db based on multiple conditions and I'm getting exception error:
"The string starts a quoted range at 69, but never ends it"
#Query("SELECT u FROM User u WHERE (u.name = ?1 and u.status= ?2)")
List<User> findUsers(String name, String status);
//at controller
#GetMapping("active")
public List<User> findUsers()
{
String name= "Ali";
String status = "ACT";
return repository.findUsers(name, status);
}
You parameter are not mapping properly.
Map the parameter using #Param
#Query("SELECT u FROM User u WHERE (u.name = :name and u.status= :status)")
List<User> findUsers(#Param("name") String name, #Param("status") String status);
Or
Use the order of method parameters in the method declaration
#Query("SELECT u FROM User u WHERE (u.name = ?1 and u.status= ?2)")
List<User> findUsers(String name, String status);

How to write JpaRepository method for searching Users that have phone number stored in Set<String>

I'm working on a Spring project and now i have to write JPA method for searching a users that have phone number LIKE in Set
The method should be in my interface UserRepository that implements JpaRepository
I have tried to write the method like:
List<User> findByNameLikeOrPhoneNumbersLike(String name, Set<String> phoneNumbers);
List<User> findByNameLikeOrPhoneNumbersLike(String name, String phoneNumber);
List<User> findByNameLikeOrPhoneNumbersContaining(String name, String phoneNumber);
But none of them works.
My class for the User Entity is:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
#Convert(converter = PhoneNumbersConverter.class)
public Set<String> phoneNumbers = new TreeSet<>();
........
}
Currently my PhoneNumbersConverter converts the list to joined String with ","
I want to write method that can search me Users on given string that may be the LIKE the name or may be LIKE one of the user Numbers.
If you're ok with using nativeQuery #Query you could do it like that (assuming that column names are name, phone_numbers and that phone_numbers looks like this 111222333,222333444,333444555).
#Query(value =
"SELECT _user FROM user _user " +
"WHERE " +
"_user.name LIKE CONCAT('%', $1, '%') OR " +
"_user.phone_numbers LIKE CONCAT('%', $1, '%')",
nativeQuery = true
)
List<User> findWhereNameOrPhoneNumberLike(String query);
You also might want to use UPPER function for both query and _user.name to be case-insensitive (UPPER(_user.name) LIKE UPPER(CONCAT('%', $1, '%'))).

Spring data jpa, jparepository returning list of string in place of DTO object

I have a interface implementing JPARepository and have three methods, one of them is having a custom #Query.
public interface PersonRepository extends JpaRepository<Person, Long> {
List<Person> getPersonBycountryCode(String countryCode);
List<Person> findByCountryCodeAndCity(String string,String city);
#Query(value = "SELECT person.firstName as firstName, person.lastName as lastName, person.countryCode as country, person.city as city,"
+ " SQRT(POWER((69.1 * (person.age - :age )) , 2 )"
+ " + POWER((53 * (person.experience - :experience )), 2)) as eligibility"
+ " FROM Person person"
+ " ORDER BY eligibility ASC")
List<PersonDetailsDto> findPersonDetailsByEligibility(
#Param("age") BigDecimal age,
#Param("experience") BigDecimal experience,
Pageable pageable
);
}
Problem is: method with #Query does not return list of PersonDetailsDto but return list of list of strings (List<List<String>>).
PersonDetailsDto is a POJO class with all the variables described in a query output (firstName, lastName, country, city, eligibility) and also a constructor with all the variables as Parameters. Other two methods does return list of Person object.
Any idea?
Actually JpaRepository<Person, Long> means that, you can use only Person as your dto in jpa repository methods.
For your solution you can just define your dto interface inside the repository :
public interface PersonRepository extends JpaRepository<Person, Long> {
List<Person> getPersonBycountryCode(String countryCode);
List<Person> findByCountryCodeAndCity(String string,String city);
#Query(value = "SELECT person.firstName as firstName, person.lastName as lastName, person.countryCode as country, person.city as city,"
+ " SQRT(POWER((69.1 * (person.age - :age )) , 2 )"
+ " + POWER((53 * (person.experience - :experience )), 2)) as eligibility"
+ " FROM Person person"
+ " ORDER BY eligibility ASC")
List<PersonDetailsDto> findPersonDetailsByEligibility(
#Param("age") BigDecimal age,
#Param("experience") BigDecimal experience,
Pageable pageable
);
//define the interface here
public interface PersonDetailsDto{
public String getFirstName();
public String getLastName();
public String getCountry();
public String getCity();
public Integer getEligibility();
}
}
If I am not wrong the idea behind JPA not looking for specific fields is that is cost (efficiency wise) the same to bring one column or all columns from one row of the table.But to solve your problem you can set nativeQuery = true in the #Query annotation from a Repository class like this:
public static final String FIND_SOMETHING = "SELECT somethingId, somethingName FROM something";
#Query(FIND_SOMETHING, nativeQuery = true)
public List<Object[]> findSomethings();
I hope this will help you to resolve your problem.
You can use new keyword in query of #Query. And make sure you have the appropriate constructor for PersonDetailsDto and also change package name.
#Query(value = "SELECT new com.company.PersonDetailsDto(person.firstName, person.lastName, person.countryCode , person.city ,"
+ " SQRT(POWER((69.1 * (person.age - :age )) , 2 )"
+ " + POWER((53 * (person.experience - :experience )), 2)) "
+ " FROM Person person"
+ " ORDER BY eligibility ASC")
List<PersonDetailsDto> findPersonDetailsByEligibility(
#Param("age") BigDecimal age,
#Param("experience") BigDecimal experience,
Pageable pageable
);
Similar question's answer.
just call it by its alias, it worked for me like that
ex :
#Query(value = "SELECT person FROM Person person"
+ " ORDER BY eligibility ASC")
List<PersonDetailsDto> findPersonDetailsByEligibility(
#Param("age") BigDecimal age,
#Param("experience") BigDecimal experience,
Pageable pageable
);

How to prevent ClassCastException with JPA entities?

I get a ClassCastException when trying to query my JPA entity class. I only want json to show two columns. That is name and address. How do I only show selected columns in JPA? From debugging it has to be the for loop. So List is the object and I need to make the right side an object instead of a list correct?
Entity
#Entity
#Table(name = "Personnel")
public class User implements Serializable {
private String id;
private String name;
private String address;
public User(String id, String name, String address)
{
this.id = id;
this.name = name;
this.address = address;
}
#Id
#Column(name = "name", unique = true, nullable = false)
public String getName() {
return this.name;
}....
//setters getters
Query/Impl
public List<User> getRecords(User ent){
String sql = "select "
+ " usr.name, usr.address "
+ " from User usr"
+ " where usr.id = '1' ";
List<User> records = this.getSession().createQuery(sql).list();
for ( User event : records ) {
System.out.println( "Records (" + event.getName + ") );
}
return records;
}
Update
This is my attempt to declare the result object as List. Does the method have to be an object instead of ?
public List<User> getRecords(User ent){
String sql = "select "
+ " usr.name, usr.address "
+ " from User usr"
+ " where usr.id = '1' ";
Map<String, String> results = new HashMap<String, String>();
List<Object[]> resultList = this.getSession().createQuery(sql).list();
// Place results in map
for (Object[] items: resultList) {
results.put((String)items[0], (String)items[1]);
results.toString();
}
return (List<User>) results;
You can pass a DTO class to the SELECT clause like this:
List<UserDTO> resultList = this.getSession().createQuery("""
select
new my.package.UserDTO(usr.name, usr.address)
from User usr
where usr.id = :userId
""")
.setParameter("userId", userId)
.getResultList();
You should read the complete object:
String sql = " from User usr"
+ " where usr.id = '1' ";
Or declare the result object as List<Object[]>
You can use generic(I assure you are using java 1.5 and above) and and one you get result, you do type check and downcast to desired type.
If You don't want to read the complete object you have to use Criteria and Projection on specific properties.
See this answer it will help

Query creation in Spring Data - dynamic where clause

Is there a way in Spring data to dynamically form the where clause?
What I want to do is have a method (which is like the findBy / get method) which runs a WHERE and AND using the mentioned properties which are NOT NULL.
For example,
Consider the object Person [firstName, lastName, age, gender]
Our method looks something like this
findBy_IfNotNullFirstName_AndIfNotNullLastName_AndIfNotNullAge_AndIfNotNullGender(String firstName, String lastName, Integer age, String gender)
Thanks.
A simpler option is to test if the parameter is null right in the JPQL query:
Exemple from my project:
#Query("select m from MessageEntity m " +
"join fetch m.demandeAnalyseEntities d " +
"where (:patientId is null or d.noPtn= :patientId) " +
" and " +
" ( :labNbr is null or d.noLab= :labNbr) " +
" and " +
" ( :reqDate is null or d.dteReq= :reqDate) " +
" and " +
" ( :reqNum is null or d.noReq= :reqNum) "
)
List<MessageEntity> findMessagesWithDemandesOnly(#Param("patientId") Long pid,
#Param("labNbr") Integer labNo,
#Param("reqDate") String reqDate,
#Param("reqNum") Integer reqNum,
Pageable pageable);
Take a look at JPA Specification and Predicate, and Even better QueryDSL, there both supported by spring data repositories.
This article provide an example:
http://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
Another solution: You can extend your JPA repo interface using custom fragment interfaces.
Define your custom methods on a new interface
public interface PersonFragRepository {
List<User> findPersonByWhatever(
String firstName, String lastName, String age, String gender);
}
Provide the implementation
public class PersonFragRepositoryImpl implements PersonFragRepository {
#PersistenceContext
private EntityManager entityManager;
#Override
List<User> findPersonByWhatever(
String firstName, String lastName, String age, String gender) {
...
}
}
Extends your JPA interface
public interface PersonRepository
extends JpaRepository<Person, Integer>, PersonFragRepository

Categories

Resources