I'm trying to set up a db query using spring-data-jpa and a native query for a postgres database. But the following does not work. Why?
#Query(value = "SELECT reltuples::bigint AS estimate FROM pg_class WHERE oid = 'public.my_table'::regclass", nativeQuery = true)
public int count();
Result:
java.lang.IllegalArgumentException: org.hibernate.QueryException: Not all named parameters have been set: [:bigint, :regclass;]
Found it: the :: have to be escaped like \\:\\:
Related
How to set null value for a column in table through spring boot JPA.
I have some requirement where I need to set null to all the records in table.
IN My repository I have written
#Modifying
#Transactional
#Query("update table_name set column_name = null")
void setNull();
In My service I have written
myRepository.rsetNull();
But for running this I am getting error like this.
Caused by: org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract void
I think the reason is that you wrote a native query in your #Query annotation, but #Query annotation by default works with JPQL queries, not with native.
As docs from #Query annotation suggests:
/** Configures whether the given query is a native one. Defaults
to {#literal false}. */ boolean nativeQuery() default false;
So, from perspective of JPQL you work with domains, not with tables.
With JPQL your query would look like:
#Modifying
#Transactional
#Query("update Domain d set d.fieldName = null")
If you want to use native query, then you should specify the flag nativeQuery = true
So, your native query would like:
#Modifying
#Transactional
#Query(value = "update table_name set column_name = null", nativeQuery = true)
I am using Spring Data JPA to get data from a MySQL database. I have this function adnotated with #Query in a repository
#Query(value = "SELECT * FROM Treatments INNER JOIN Animals ON Treatments.animal_id = Animals.animal_id WHERE Animals.owner_id = ?1 AND Treatments.enddate > curdate()", nativeQuery = true)
Page<Treatments> findAll(#Param("ownerId") Optional<Owner> owner, Pageable pageable);
Spring generates the SQL as it is, then adds order by INNER.startdate asc limit ?
And then it throws this error
Unknown column 'INNER.startdate' in 'order clause'
Why is this happening? I tried adding an orderby clause myself but it will just add its own orderby clause anyway and throw the error. The query works inside MySql.
I suppose Spring modifies your query because you use Page as the return type. When you use a native query together with Page, you should add a countQuery, see Spring Documentation.
I found similar questions about this error but I can't make it work
I'm working on a java 8, spring 2.6.4 and a MySQL database
I'm trying to do a DELETE native query using JPA and I'm getting this error:
org.springframework.orm.jpa.JpaSystemException: could not extract ResultSet; nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet
this is my query:
#Query(value = "DELETE FROM reservation a WHERE a.slotid =:slotid", nativeQuery = true)
void deleteWhereSlotid(Integer slotid);
and this is the service:
repo.deleteWhereSlotid(reservationSlot.getId());
I've also tried:
#Query(value = "DELETE FROM reservation a WHERE a.slotid =:slotid", nativeQuery = true)
Object deleteWhereSlotid(Integer slotid);
//service
Object object= userCourseResRepo.deleteWhereSlotid(reservationSlot.getId());
but it failed
Usually I delete rows with deleteById(id) which comes with spring
The query works though, I tried it on phpMyadmin console and it worked
Someone know what I can try?
The way you have it set up, Spring Data assume you want to perform a query (typically a SELECT). For DELETE and similar statements that don't return a ResultSet you need to provide an additional #Modifying annotation.
#Modifying
#Query(value = "DELETE FROM reservation a WHERE a.slotid =:slotid", nativeQuery = true)
void deleteWhereSlotid(Integer slotid);
I know is not the best solution, but you can try to use a query SELECT to find your reservation object and then do this repo.deleteById(reservation.getId())
This should allow you to go ahead while you find a better way to do it
If you are using it that way, I believe the query should be:
DELETE a FROM reservation a WHERE a.slotid =:slotid
I am not particularly sure about the code, however, with Mysql, the case seems to be so when giving an alias to the table.
You need to add #Param
#Query(value = "DELETE FROM reservation a WHERE a.slotid =:slotid", nativeQuery = true)
Object deleteWhereSlotid(#Param("slotid")Integer slotid);
As mentioned above, we use the #Param annotation in the method declaration to match parameters defined by name in JPQL/Native query with parameters from the method declaration.
I am using Hibernate/JPA to execute native PostGIS queries. The problem with these queries is that they need parameters that are not of the classical X = 'value' form.
My query is :-
#Modifying
#Query(value="UPDATE memo SET readMemo = true and updatedBy_id = ?1 and updatedBy = ?1 and updatedOn = ?2 where assignToUser_id = 1? and readMemo = false and deleted = false ",nativeQuery = true)
void readAllMenoByCurrentUser(Long id, Date updateTime);
Error :-
org.springframework.dao.InvalidDataAccessApiUsageException: Cannot mix JPA positional parameters and native Hibernate positional/ordinal parameters; nested exception is java.lang.IllegalArgumentException: Cannot mix JPA positional parameters and native Hibernate positional/ordinal parameters
Does anyone know how to solve in this case ?
You have "1?" in your query. This will mean it tries to interpret that as a "?" (SQL parameter) rather than positional parameter. Change it to "?1"
Let's say we have an entity called MyEntity. It is possible to query pageable results using #Query and with named queries, e.g.
#Query(value = "select e from MyEntity e where e.enabled = true")
Page<MyEntity> findAllEnabled(Pageable pageable);
However, it is not possible to achieve the same with native query, so this
#Query(value = "select * from my_entity where enabled = true", nativeQuery = true)
Page<MyEntity> findAllEnabled(Pageable pageable);
won't work.
What are the reasons behind this? Is it possible to make Pageable working with native queries?
I don't know if this is still relevant to you: At least in Spring Data JPA 1.9.4 you can specify two queries.
Given a repository:
interface FoobarEntityRepository extends JpaRepository<FoobarEntity, Integer> {
Page findFoobarsSpecialQuery(String someParameter, final Pageable pageable);
}
You can add 2 native queries to your entity, one for the query itself and one for the count statement:
#Entity
#SqlResultSetMappings({
#SqlResultSetMapping(name = "SqlResultSetMapping.count", columns = #ColumnResult(name = "cnt"))
})
#NamedNativeQueries({
#NamedNativeQuery(
name = "FoobarEntity.findFoobarsSpecialQuery",
resultClass = DailyPictureEntity.class,
query = "Select * from foobars f where someValue = :someParameter "
),
#NamedNativeQuery(
name = "FoobarEntity.findFoobarsSpecialQuery.count",
resultSetMapping = "SqlResultSetMapping.count",
query = "Select count(*) as cnt from foobars f where someValue = :someParameter "
)
})
FoobarEntity {
}
The trick is to specify the count query with the suffix .count. This works also with the Spring Data #Query annotation.
Notice that you need a SQL result set mapping for the count query, though.
This works actually pretty nice.
This is description, given in spring data jpa documentation (http://docs.spring.io/spring-data/jpa/docs/1.8.0.M1/reference/html/)
Native queriesThe #Query annotation allows to execute native queries
by setting the nativeQuery flag to true. Note, that we currently don’t
support execution of pagination or dynamic sorting for native queries
as we’d have to manipulate the actual query declared and we cannot do
this reliably for native SQL.
JPQL abstracts SQL implementation and it's providers specifics, and makes it responsibility of ORM framework to generate correct SQL.
So by using Pagination in JPQL form, Spring just needs to generate correct JPQL, and it will be interpreted on ORM level to correct SQL.
While doing so with SQL, would imply that Spring knows how to generated correct SQL for the vast majorities of RDBMS, duplicating ORM functionality, which is too much overhead.
There is a way to use Pageable with native queries with the SpEL capacity of Spring data, it is mention here.
You can find an example in this repository.
/**
* #see DATAJPA-564
*/
#Query(
value = "select * from (select rownum() as RN, u.* from SD_User u) where RN between ?#{ #pageable.offset -1} and ?#{#pageable.offset + #pageable.pageSize}",
countQuery = "select count(u.id) from SD_User u", nativeQuery = true)
Page<User> findUsersInNativeQueryWithPagination(Pageable pageable);
The sort functionnality will not work properly if there is a subquery in the fromclause or your native query and you wish to apply a dynamic sort on it. The way it can be done is to move the subquery in the where clause.
Spring data will append to the end of your request " order by " if there is a Sort object in the Pageable. (with Spring data 1.10.3)
A better way is to convert the native query in jpql if possible.