CrudRepository Spring Data #Query syntax - spring

The #Query annotation supports only JPA query syntax or Hibernate (HQL)? or both of them i am kinda confused
interface TodoRepository extends CrudRepository<Todo, Long> {
#Async
#Query("SELECT t.title FROM Todo t where t.id = :id")
Book<String> findTitleById(#Param("id") Long id);

SpringData repositories support JPQL (Java Persistence Query Language).
Though JPQL is a subset of HQL so any JPQL query is a valid HQL query.
The inverse is obviously not true.

Related

Dynamic where clause in custom query JPA

How to pass where clause whitout using query dsl or custom repository?
public interface PlTransactionsRepository extends PagingAndSortingRepository<PlTransactions, Integer>, JpaSpecificationExecutor<PlTransactions> {
#Query(value = "SELECT a FROM PlTransactions :whereClause")
List<PlTransactions> selectTrxForRecon(#Param("whereClause") Integer whereClause);
}
For dynamic where queries, you shouldn't use JPQL but Criteria API or the Spring Data JPA JpaSpecificationExecutor
If you implement JpaSpecificationExecutor you'll get find methods where you can pass a Specification. A Specification will form the dynamic where clause.
Please find more information in the documentation:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications

Pass SQL statement to JPA #Query

Is there a way to pass the whole sql statement or a part of it to #Query annotation?
#Modifying
#Query(value = "INSERT INTO my_table :query", nativeQuery = true)
#Transactional
void test(#Param("query") String query);
I think a viable option for you would be to use the entity manager, instead of the repository. You can do it using NativeQuery and its executeUpdate method. Please check:
Inserting in my JPA using entity manager native query

Using Querydsl and JPAQuery within a Spring repository for large or complex queries?

In a Spring Boot application using a #Repository with derived queries is somewhat easy.
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
}
If, however, the queries are getting more complex (joins, subqueries, etc.) then we're using Querydsl like in the following pseudo-code example.
JPAQuery<User> query = new JPAQuery<>(entityManager);
List<User> deletableUsers = query
.select(user)
.from(user)
.join(someTable)
.on(user.id.eq(someTable.user.id))
.where(user.notIn(createSubquery(compareDate))
.and(condition1)
.and(condition2)
.and(condition3)
.distinct()
.fetch();
private JPQLQuery<User> createSubquery(Date compareDate) {
return JPAExpressions
.select(user)
.from(user)
.join(someOtherTable)
.on(user.id.eq(someOtherTable.user.id))
.where((condition4
.and(condition5)
.and(condition6)))
.distinct();
}
Currently, we're using this query from within a #Service class but I wonder if it might make sense to move that to the Spring repository, so that all "query related" methods are located in the repository.
Is such an approach feasible, i.e. do you see any impediments like injecting the EntityManager into the repository?
Would you rather recommend to use the #Query annotation despite the query string getting long and complex?

How return column from my DB using Java Spring JPQL

I have a very basic task. I want to return just one column from my table in my DB. Literally, I want the text from my category_name. This is my JPQL cod:|
#Transactional
#Modifying
#Query(value = "SELECT category_name FROM Category WHERE id=:id", nativeQuery = true)
String findName(#Param("id") long id);
And I have this error:
Modifying queries can only use void or int/Integer as return type!
As the error apparently states, you should use #Modifying annotation when you are actually updating/deleting the row. Since you are fetching data from already stored database, you can simply remove this annotation.
You should also remove #Transactional annotation.
https://dzone.com/articles/how-does-spring-transactional is an interesting article to know about how transactional annotation works and when it should be used.

Springboot 1.5.7 / SpringDataJPA - Why methods in repository are not all transactional by default

This code in my repository :
public interface ClientRepository extends CrudRepository<Client, Long> {
//#Transactional
#Modifying
#Query("update Client c set c.firstName = ?1, c.lastName = ?2, c.email = ?3 where c.id = ?4")
void updateClientInfoById(String firstname, String lastname, String email, Long userId);
Executing this method(updateClientInfoById) using a REST Service give me this exception : javax.persistence.TransactionRequiredException: Executing an update/delete query
I Have to add #Transactional to get it works.
why methods in repository are not all transactional by default ?
Thanks in advance :)
Only CRUD methods are by default marked as transactional. You are using custom query methods so you should explicitly mark it with #Transactional annotation.
Additionally, we can get rid of the #Transactional annotation for the
method as the CRUD methods of the Spring Data JPA repository
implementation are already annotated with #Transactional.
For more informations, see Getting started with Spring Data JPA
EDIT : CRUD methods are CrudRepository methods

Resources