Pass list in JPA named native query - jpa

We want to pass list of strings into JPA named native query.How we can achieve this.it is throwing invalid query parameter exception.

#Query(value = "select e from student so where so.name in ?1", nativeQuery = true)
List<Student> someFunName(List<String> stringList);
U can try something like this for a nativeQuery, for list of string as param.
(I just gave an example for Entity Student)

Related

Spring jpa returning specific column without nativeQuery

I trying to select from database specific column only
public interface ItemRepository extends PagingAndSortingRepository<Item,String> {
#Query("SELECT i.id FROM Item i where i.id =?1")
Optional<Item> getit(String id);
}
But instead of returning Object Item it returns String (the id value).
How Can I return the object? (I can't add any constructors to it)
p.s. if I use nativeQuery it does work.
This query in JQL can be simpler.
#Query("SELECT i FROM Item i where i.id =?1")
Optional<Item> getit(String id);
Or even
#Query("FROM Item where id =?1")
Optional<Item> getit(String id);
However, since you are already using JPA, you don't need to define any method with a #Query annotation.
findById is already defined.
Optional<Item> itemOpt = itemRepository.findById(id);

Spring data repository how to query ElementCollection of String containing substring

I have an entity with an #ElementCollection of strings:
#ElementCollection(fetch = FetchType.EAGER)
private Set<String> names;
While it is no problem to query by names:
List<MyEntity> findByNames(String name);
It seems not to work if i try to create a method with "contains". I want to find entities that have a matching name that contains given substring:
List<MyEntity> findByNamesContains(String substringOfname);
This yields no results but also no error. It seems that the "contains" keyword here is interpreted as the list of name should contain. If i change it to
List<MyEntity> findByNamesContains(List<String> substringOfname);
This methods works.
My question is: is there a combination of keywords to get a method that returns all entities that have a name matching a given substring?
If not how would a JPQL query look like?
As far I knew, No you can't do it wit Spring-JPA-Date repository method names, but it's very easy to be done with JPQL and Spring repository
here's JPQL
select e from MyEntity e join e.names name where name LIKE CONCAT('%', :name, '%')
for case-insensitive query use this
select e from MyEntity e join e.names name where LOWER(name) LIKE CONCAT('%', LOWER(:name), '%')
JPQL + Spring repository
#Query("select e from MyEntity e join e.names name where name LIKE CONCAT('%', :name, '%') ")
List<MyEntity> findByName(#Param("name") String name);
for more information use look here and this answer, Hope this help (:
In case of single string use containing keyword. Works in the same way as "like" in sql queries.
Ref: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#_supported_query_keywords

How to avoiding AND condition if parameter is null in Spring Data JPA query

I am trying to get the result of one query using Spring Data JPA. Here I am sending some parameter and receiving result according to that.
My repository query is,
#Query("select u.username,p.pname from Users u join u.priviJoin p where u.username = :uname AND p.pname = :pname")
List<Users> findByUsername(#Param("uname") String uname , #Param("pname") String pname );
And calling from controller like the following,
#RequestMapping(value = "/joinResult", method = RequestMethod.GET)
public List<Users> joinResultShow()
{
return (List<Users>) userRepo.findByUsername("test_user","testRole");
}
Here we can see that if I am passing some value then only checking according to that parameter. Here I need to modify my query like if parameter is null, then not need to use AND condition in query.
How can I modify this query for avoiding AND condition if parameter is null? I am new to Spring Data JPA world.
Here are some possible options for you
1. Create multiple methods in your repository like
#Query("select u.username,p.pname from Users u join u.priviJoin p where u.username = :uname AND p.pname = :pname")
List<Users> findByusernamewithRole(#Param("uname") String uname , #Param("pname") String pname );
#Query("select u.username,p.pname from Users u join u.priviJoin p where u.username = :uname")
List<Users> findByUsernameWithoutRole(#Param("uname") String uname);
Write a custom respository and use EntityManager. With this you can create a dynamic queries based on your input using CriteriaBuilder and use this criteria in querying.
Last and the most preferred option in case of dynamic inputs(like you have) is Querydsl.
Some articles about querydsl
http://www.baeldung.com/querydsl-with-jpa-tutorial
http://www.querydsl.com/static/querydsl/latest/reference/html/ch02.html

Native query not working when specifying column name

I am trying to fetch data using native query method. I am able to fetch data using spring data JPA repository declared methods (findAll() etc) and using JPQL Queries.
When I am using Native query method , "select * from" is working. But when I am specifying "select username from " method is not working. Means When specifying column name, it is not working.
I am adding my code like this,
#Query(value = "select u.username from users u" , nativeQuery = true)
List<Users> findByUsername();
But the query using select * from users is working with no problem. Is this native query nature? Or is there any limited type of format the provider defines?
I think the problem is with your return variable.
When you run "*select * from...*" query, you can return list of Users.
However, you want to fetch a column which is probably a varchar, so that you should return List of String:
#Query(value = "select u.username from users u" , nativeQuery = true)
List<String> findByUsername();

Passing List<Integer> in spring data jpa native query

Using spring data JPA, I am trying to make this sort of query (it is more complex, this is a simple case)
#Query(nativeQuery = true,
value = "SELECT * FROM events WHERE typeId IN (?1)")
List<Event> findEventsByType(List<Integer> types);
When I launch the query, an exception raises:
org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.util.ArrayList. Use setObject() with an explicit Types value to specify the type to use.
I have tried List < Integer >, Integer[], Object[] and String but it is not working...
Can't I pass list of values?
Which is the best approach to make this sort of queries?
Thanks!
Try taking away the #Query and make the method name:
public List<Event> findByTypeIn(List<Integer> types);
See table 2.2 in the link: http://docs.spring.io/spring-data/jpa/docs/1.2.0.RELEASE/reference/html/
I tried like below and it works for me.
#Query(value = "select * from events where type_id in :types", nativeQuery = true)
List<Event> findEventsByType(#Param("types") List<Integer> types);
#Query(value = "SELECT c from Company c where " +
"c.companyName IN (:company_names)")
List<Company> findCompaniesByName(#Param("company_names") List<String> companyNames);
This is the solution to your problem.
Here I am passing List which contains company names and I am querying DB and storing result in List.
Hope this hepls!
Use JPQL. A native query is or should be passed to the database exactly as you have created the SQL string, and unless your driver can take a serialized collection and understand that the single parameter needs to be interpreted as many, it just won't work. The collection you pass in needs the SQL expanded from (?) to (?, ?,...) based on the number of elements in a collection, and JDBC drivers just are not able to do this, and JPA providers are required to execute the string as is.
A JPQL query allows the JPA provider to create the SQL it needs dynamically based on the list passed in, so it can expand the collection for you.
Try this. It will work for Native Query in SpringBoot JPA:
#Query(value = "SELECT * FROM table WHERE columnName IN (:inputList)" ,
nativeQuery = true)
List<Object> findByObjectList(#Param("inputList") List<Object> inputList);
And also in case of JPA, try the below :
List<Object> findByObjectList(List<Object> inputList)
I know this is a little bit out of context (we use Update and not Select), but this can be usefull for others :
/**
* Update the state of list of entities using their ids
* #param ids request ids
* #param state new state
* #return
*/
#Modifying
#Query(value = "UPDATE AbstractRequest SET state = :state WHERE id IN (:ids)")
int updateStates(#Param("ids") List<Long> ids, #Param("state") InternalRequestStep state);
pass array this way inside IN Clause
#Query(value = "select name from teams where name in :names", nativeQuery = true)
List<String> getNames(#Param("names") String[] names);
Call this way
String[] names = {"testing team","development team"};
List<String> teamtest = teamRepository.getNames(names);
Remove brackets around (?1) parameter. Your query value should look like that:
#Query(value = "SELECT * FROM events WHERE typeId IN ?1")
try querying like this:
#Query(nativeQuery = true,
value = "SELECT * FROM events WHERE typeId = ?1")
List<Event> findEventsByType(List<Integer> types);
did it work?