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"
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'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 \\:\\:
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.
I have a named query as below;
#NamedQuery(name = "MyEntityClass.findSomething", query = "SELECT item FROM MyTable mytbl")
Now I want to append dynamic sort clause to this query (based on UI parameters)
Can I get an example using JPQL for doing the same (like how to set a dynamic ORDER BY in the Entity class)
I have already tried using CriteriaQuery, but was looking for a JPQL implementation now.
NamedQueries are by definition NOT dynamic, it is not correct to change them programmatically.
So the way to go is to create a JPQL query (but not a named query) like this:
TypedQuery<MyEntity> query = em.createdQuery("SELECT item FROM MyEntity item ORDER BY "+sortingCol, MyEntity.class);
On the other hand, if you REALLY want to use the named query, you could do that the following way:
#NamedQuery(name = "MyEntityClass.findSomething", query = MyEntity.NAMED_QUERY)
#Entity
public class MyEntity {
public static final NAMED_QUERY= "SELECT item FROM MyTable mytbl";
//+your persistent fields/properties...
}
//and later in your code
TypedQuery<MyEntity> query = entityManager.createQuery(MyEntity.NAMED_QUERY + " ORDER BY " + sortingCol, MyEntity.class);
Complementing for JPA 2.1
As of JPA 2.1 it is possible to define named queries programmatically.
This can be achieved using entityManagerFactory.addNamedQuery(String name, Query).
Example:
Query q = this.em.createQuery("SELECT a FROM Book b JOIN b.authors a WHERE b.title LIKE :title GROUP BY a");
this.em.getEntityManagerFactory().addNamedQuery("selectAuthorOfBook", q);
// then use like any namedQuery
Reference here
This can be useful, for instance, if you have the orderby field defined as a application parameter. So, when the application starts up or on the first run of the query, you could define the NamedQuery with the defined OrderBy field.
On the other side, if your OrderBy can be changed anytime (or changes a lot), then you need dynamic queries instead of NamedQuery (static). It would not worth to (re)create a NamedQuery every time (by performance).
#NamedQuery
Persistence Provider converts the named queries from JPQL to SQL at deployment time.
Until now, there is no feature to create/update the query with #NamedQuery annotation at runtime.
On the other hand, you can use Reflection API, to change the annotation value at runtime. I think It is not solution, also it is not you wanted .
em.createQuery()
Persistence Provider converts the dynamic queries from JPQL to SQL every time it is invoked.
The main advantage of using dynamic queries is that the query can be created based on the user inputs.