No value specified for parameter - CrudRepository - spring

public interface UserRepository extends CrudRepository<User, Integer> {
#Query(value = "select u from User u")
List<User> selectAllUsers();
#Query(value = "select u from User u where u.username = ?1")
User findByName(String name);
#Query(value = "select u from User u where u.id = ?1")
User findById(Integer id);
#Modifying
#Transactional(readOnly = false)
#Query("UPDATE User u SET u.friends = ?1 WHERE u.id = ?2")
Integer setNewFriendsForId(Set<User> friends, Integer id);
}
Spring provides me with implementation of this interface that is used in class called UserService. But when I try to execute this method I get a really huge stack of exceptions.
userService.setNewFriendsForId(invitingUser.getFriends(), invitingUser.getId());
The root cause is:
org.postgresql.util.PSQLException: No value specified for parameter 2.
org.postgresql.core.v3.SimpleParameterList.checkAllParametersSet(SimpleParameterList.java:178)
org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:246)
org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
(...)
Any ideas what can be the reason? Select queries work right.

Reason is that collection valued field (u.friends) cannot be updated. In JPA 2.0 specification this is told with following words:
update_statement ::= update_clause [where_clause]
update_clause ::= UPDATE entity_name [[AS] identification_variable]
SET update_item {, update_item}*
update_item ::= [identification_variable.]{state_field
| single_valued_object_field} = new_value
new_value ::= scalar_expression | simple_entity_expression | NULL
Update operation works only for single value fields as in following:
UPDATE User u SET u.someSingleValuedField = ?1

Related

Spring boot JPA native query and pagination using countQuery

I saw this example for native query which use countQuery:
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 ORDER BY ?#{#pageable}",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
And the second example:
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value="SELECT * FROM USERS WHERE LASTNAME = ?1", nativeQuery=true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
The second example does not use countQuery, so what in the best practice? Can you explain ?
I tried both and both work well. What is the best practice ?
You can omit it if it is the same as your original query.
From the documentation :
countQuery
Defines a special count query that shall be used for pagination queries to lookup the total number of elements for a page. If none is configured we will derive the count query from the original
query or countProjection() query if any.
countQuery is useful when you need a different query to compute total items (this should almost never be the case though).
Note that countQuery can also be needed when you have a Pageable along with a non-native query, and need to fetch lazy loaded associations.
For example, let's assume your User entity has a lazy loaded registrations association :
This will not compile (query validation should fail with the below error message) :
#Query(value = "select u from Users u left join fetch u.registrations where lastName = ?1")
Page<User> findByLastname(String lastname, Pageable pageable);
org.hibernate.query.SemanticException: query specified join fetching,
but the owner of the fetched association was not present in the select
list
This will work :
#Query(value = "select u from Users u left join fetch u.registrations where lastName = ?1",
countQuery = "select u from Users u left join fetch u.registrations where lastName = ?1")
Page<User> findByLastname(String lastname, Pageable pageable);
(Note that you could have used #EntityGraph in that later case, this is just to demonstrate a use case of the countQuery where it is required).

How to get payload display as below? I wanted to join multiple roles access into one array(Native Query) as shown in the second example

I a intern student,I tried join table use native query (user, role ,access)it success but when I use get mapping to display role_name and access by email, the payload display not like I want.
Payload when I get by email,I don't display like this. Example 1
Payload I want to get. I want to be display like this. Example 2
Here is my code:
UserRepository.java
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT users.name, users.email, role.role_name, access.acc_name FROM users LEFT JOIN user_role ON user_role.user_id = users.id LEFT JOIN role ON role.rid = user_role.role_id LEFT JOIN role_access ON role_access.role_id = role.rid LEFT JOIN access ON role_access.access_id = access.id WHERE users.email= :email", nativeQuery = true)
List<Map<String, Object>> findUserByRoleIdByAccessById(#Param("email") String email);
}
--
UserController.java
#GetMapping("/users/access/{email}")
public List<Map<String, Object>> getuserAccess(#PathVariable(value = "email") String email) {
return userRepository.findUserByRoleIdByAccessById(email);
}

How do I use custom SQL in sprint data repository?

I`m using Repository like this:
public interface UserRepository extends Repository<User, Long> {
List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}
But what I need is execute my own sql statement.
select u.* from users u where exists ( select 1 from expires_users where users_id = u.id )
Please, past link references in answers.
I think you can do as pointed in the documentation of Spring Data JPA.
Here is an example:
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select u.* from User u
where exists(select 1 from ExpiredUser e where e.id = u.id)")
Page<User> findExpiredUsers(Pageable pageable);
}
The Page and Pageable parts are for paging results, assuming that this query could return many more results than you would like to process at once. More information on paging results can be found here.

Pagination error in SpringBoot "Incorrect syntax near '#P0'" [duplicate]

I'm using Spring Data JPA, and when I use #Query to to define a query WITHOUT Pageable, it works:
public interface UrnMappingRepository extends JpaRepository<UrnMapping, Long> {
#Query(value = "select * from internal_uddi where urn like %?1% or contact like %?1%",
nativeQuery = true)
List<UrnMapping> fullTextSearch(String text);
}
But if I add the second param Pageable, the #Query will NOT work, and Spring will parse the method's name, then throw the exception No property full found. Is this a bug?
public interface UrnMappingRepository extends JpaRepository<UrnMapping, Long> {
#Query(value = "select * from internal_uddi where urn like %?1% or contact like %?1%",
nativeQuery = true)
Page<UrnMapping> fullTextSearch(String text, Pageable pageable);
}
You can use pagination with a native query. It is documented here: Spring Data JPA - Reference Documentation
"You can however use native queries for pagination by specifying the count query yourself:
Example 59. Declare native count queries for pagination at the query method using #Query"
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
A similar question was asked on the Spring forums, where it was pointed out that to apply pagination, a second subquery must be derived. Because the subquery is referring to the same fields, you need to ensure that your query uses aliases for the entities/tables it refers to. This means that where you wrote:
select * from internal_uddi where urn like
You should instead have:
select * from internal_uddi iu where iu.urn like ...
Considering that the UrnMapping class is mapped to the internal_uddi table, I would suggest this:
#Repository
public interface UrnMappingRepository extends JpaRepository<UrnMapping, Long> {
#Query(value = "select iu from UrnMapping iu where iu.urn like %:text% or iu.contact like %:text%")
Page<UrnMapping> fullTextSearch(#Param("text") String text, Pageable pageable);
}
Please note that you might have to turn off native queries with dynamic requests.
With #Query , we can use pagination as well where you need to pass object of Pageable class at end of JPA method
For example:
Pageable pageableRequest = new PageRequest(page, size, Sort.Direction.DESC, rollNo);
Where,
page = index of page (index start from zero)
size = No. of records
Sort.Direction = Sorting as per rollNo
rollNo = Field in User class
UserRepository repo
repo.findByFirstname("John", pageableRequest);
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USER WHERE FIRSTNAME = :firstname)
Page<User> findByLastname(#Param("firstname") String firstname, Pageable pageable);
}
Please reference :Spring Data JPA #Query, if you are using Spring Data JPA version 2.0.4 and later. Sample like below:
#Query(value = "SELECT u FROM User u ORDER BY id")
Page<User> findAllUsersWithPagination(Pageable pageable);
Declare native count queries for pagination at the query method by using #Query
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
Hope this helps
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
Rewrite your query to:
select iu from internal_uddi iu where iu.urn....
description: http://forum.spring.io/forum/spring-projects/data/126415-is-it-possible-to-use-query-and-pageable?p=611398#post611398
I found it works different among different jpa versions, for debug, you'd better add this configurations to show generated sql, it will save your time a lot !
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
for spring boot 2.1.6.RELEASE, it works good!
Sort sort = new Sort(Sort.Direction.DESC, "column_name");
int pageNumber = 3, pageSize = 5;
Pageable pageable = PageRequest.of(pageNumber - 1, pageSize, sort);
#Query(value = "select * from integrity_score_view " +
"where (?1 is null or data_hour >= ?1 ) " +
"and (?2 is null or data_hour <= ?2 ) " +
"and (?3 is null or ?3 = '' or park_no = ?3 ) " +
"group by park_name, data_hour ",
countQuery = "select count(*) from integrity_score_view " +
"where (?1 is null or data_hour >= ?1 ) " +
"and (?2 is null or data_hour <= ?2 ) " +
"and (?3 is null or ?3 = '' or park_no = ?3 ) " +
"group by park_name, data_hour",
nativeQuery = true
)
Page<IntegrityScoreView> queryParkView(Date from, Date to, String parkNo, Pageable pageable);
you DO NOT write order by and limit, it generates the right sql
I had the same issue - without Pageable method works fine.
When added as method parameter - doesn't work.
After playing with DB console and native query support came up to decision that method works like it should. However, only for upper case letters.
Logic of my application was that all names of entity starts from upper case letters.
Playing a little bit with it. And discover that IgnoreCase at method name do the "magic" and here is working solution:
public interface EmployeeRepository
extends PagingAndSortingRepository<Employee, Integer> {
Page<Employee> findAllByNameIgnoreCaseStartsWith(String name, Pageable pageable);
}
Where entity looks like:
#Data
#Entity
#Table(name = "tblEmployees")
public class Employee {
#Id
#Column(name = "empID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotEmpty
#Size(min = 2, max = 20)
#Column(name = "empName", length = 25)
private String name;
#Column(name = "empActive")
private Boolean active;
#ManyToOne
#JoinColumn(name = "emp_dpID")
private Department department;
}
When using nativeQuery that is having (nativeQuery = true), you may do the pagination yourself in the query by adding (LIMIT :sizeValue OFFSET :page)
Note:
Your page value passed to this method should be offset * size
Example
#Query(value = "SELECT * FROM person " +
"LIMIT ?1 OFFSET ?2", nativeQuery = true)
Optional<List<TDriverJob>> findPersons(int size, int page);
I tried all above solution and non worked , finally I removed the Sorting from Pagination and it worked
the following tutorial helped me
-> https://www.baeldung.com/spring-data-jpa-query
At this point 4.3. Spring Data JPA Versions Prior to 2.0.4
VERY IMPORTANT to add \ n-- #pageable \ n
Without this I was wrong
Also the pagination setting must be without ordering
PageRequest paginaConf = new PageRequest ((param1 - 1)
, param2);
Finally to convert the Page <Object []>
Page <Object []> list = myQueryofRepo ();
List <XXXModel> lstReturn = myConversor (list.getContent ());
Page <XXXModel> ret = new PageImpl <XXXModel> (lstReturn, pageConf, param2);
This bugged me for a while but I managed with a very smooth solution.
The challenge is JPA did not automatically detect the count query so I resolved to use the countName which according JPA docs Returns the name of the javax.persistence.NamedQuery to be used to execute count queries when pagination is used. Will default to the named query name configured suffixed by .count.
So I created a named query
#NamedNativeQuery(
name = "[queryName].count",
query = [your count query],
resultSetMapping = "[query resultSetMapping name]"
)
}
As indicated, the count query should be suffixed with .count
Count query returns Long so add the resultSetMapping as
#SqlResultSetMapping(
name="[query resultSetMapping name]",
columns={#ColumnResult(name="count", type = Long.class)})
Then in your repository, use the count query as indicated below
#Query(countName ="[queryName].count" , nativeQuery = true)
Page<Object> [mainQuery](...params)
Hope this helps!

Annotations are not allowed here

I'm creating a UserRepository which implements JpaRepository and works with User entity. I need a method to update username. I decided to do it with the help of #Query. But it's marked by Intellij. Here is my code for repository:
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
#Modifying
#Query(value = "update User user set user.name= %?username"))
void updatingUser(#Param(value = "username") String username);
}
And for Entity:
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private Long id;
#NotNull
#Column(name = "user_name")
private String username;
}
And I faced with such a problem: "Annotations are not allowed here" says Intellij Idea and marks the line with #Query annotation. And it made me confused
In my case, I accidentally typed ";" at the end of #Query. Might help someone else.
Sorry, guys. It was so stupid for me to write double quotes in the end of this line. But I actually don't understand why Intellij didn't notice that but started to mark this line with another mistake
In my case, I accidently typed an ';' at the end of the #Query sentence.
#Query("SELECT a FROM Author a")
#QueryHints(value = #QueryHint(name = HINT_FETCH_SIZE, value= "" + Integer.MIN_VALUE));
Stream<Author> streamAll();
After I removed the ';' from the #QueryHints, then it worked perfectly.
#Query("SELECT a FROM Author a")
#QueryHints(value = #QueryHint(name = HINT_FETCH_SIZE, value= "" + Integer.MIN_VALUE))
Stream<Author> streamAll();
Sorry this was 4 years too late, but you have an extra ')' at the end of your #Query line
Using the #Query annotation in this place is absolutely appropriate. But your query is not quite correct.
Query parameters can be named - ':name' or indexed - '?1'.
You should use update queries with 'where' clause otherwise you will update all records.
You code should be like this:
#Modifying
#Query("update User u set u.name = ?1 where u.name = ?2")
void updateByName(String value, String name);
Or like this:
#Modifying
#Query("update User u set u.name = :value where u.name = :name")
void updateByName(#Param("value") String value, #Param("name") String name);
Pay attention - while the 'name' field is not unique you will update ALL users with given 'name'. To update only one user you must use unique field or primary key in the 'where' clause, for example:
#Modifying
#Query("update User u set u.name = ?1 where u.id = ?2")
void updateById(String value, Long id);
By the way if you need to update all user which have specific name pattern - use 'like' operator:
#Modifying
#Query("update User u set u.name = ?1 where u.name like '%'||?2||'%'")
void updateByNameLike(String value, String name);
Useful info:
Spring Data JPA - Reference Documentation
JPQL Language Reference
SQL Tutorial
P.S. Annotation #Repository is not necessary
Well, I got this issue with the following query after copying from SQLyog.
SELECT id FROM (SELECT * FROM departments ORDER BY id) dpt_sorted, (SELECT #pv := '2') initialisation WHERE FIND_IN_SET(parent_dept, #pv) AND LENGTH(#pv := CONCAT(#pv, ',', id));
But when i typed the query, the error message disappeared. May be copy and paste issue in my case. This could be helpful.
In my case, I was trying to use it in the constructor...

Resources