Pageable usage with Query Annotation - r2dbc

Can I use Pageable attribute in Spring Data R2dbc repositories with #Query annotation? For example;
public interface PartyRepository extends ReactiveCrudRepository<Party,String> {
#Query("select * from party order by id")
Flux<Party> getParties(Pageable pageable);
}
It gives "org.springframework.data.repository.query.ParameterOutOfBoundsException : Invalid parameter index! You seem to have declared too little query method parameteres!"
Is there any way to use pagination in spring Data R2dbc repositories?
Thanks.

This is not supported by R2DBC and probably never will.
But you can adjust the query string with SpEL expressions manually to include paging. For MySQL, in your example, this could look like this:
#Query("SELECT * FROM party ORDER BY id LIMIT :#{[0].offset},:#{[0].pageSize}")
Flux<Party> getParties(Pageable pageable);
The [0] part indicates which argument in your argument list is the Pageable.

Related

Spring Data Rest findByIdIn

We use Spring Data Rest to build simple API for our internal webapp.
Our repositories as below:
public interface BaseRepository<T, ID extends Serializable> {
List<T> findByIdIn(#Param("ids") Collection<ID> ids);
}
public interface FooRepository extends BaseRepository<Foo, String> {}
public interface BarRepository extends BaseRepository<Bar, Long> {}
Our client fetch data, passing ids parameters as below:
GET http://example.com/api/foos/search/findByIdIn?ids=ABC,XYZ --> It works well for String ids.
GET http://example.com/api/bars/search/findByIdIn?ids=1,2,3 --> Got exception for numeric ids.
We got the exception: Parameter value element[1] did not match expected type [java.lang.Long (n/a)]
What's wrong with above repositories? What is the correct way to pass numeric ids?
You may use this library which lets you build advanced search queries: https://github.com/turkraft/spring-filter
You can then simply do:
?filter= ids in (1, 2, 3, 4)
It supports enums, dates, booleans, logical operations, comparisons, and even joins (nested fields).

Jpa createSQLQuery returns List<Object> instead of List<Employee>

Trying to make an sql query to get as a result a list of Class "EmployeeCardOrderLink". But this code always returns me an list of Object. Casts doesn't working. I got the right data in this list, but it's just object. In debug i can call methods(Idea suggest according interface of my class), but then i got "class Object doesn't have a such method". And i can't use TypedQuery cause i have old JPA version, it doesn't support this.
#Repository
public class EmployeeCardOrderLinkDAOImpl extends AbstractBasicDAO<EmployeeCardOrderLink> implements EmployeeCardOrderLinkDAO {
//....
#Override
public List<EmployeeCardOrderLink> getLinksByOrderNumber(Integer num) {
List<EmployeeCardOrderLink> result = (ArrayList<EmployeeCardOrderLink>) getSessionFactory().getCurrentSession().createSQLQuery("select * from employee_card_order_links " +
"where trip_order_id = " + num).list();
return result;
}}
You use Hibernate (not JPA), if you are using Session. Hibernate is JPA provider of course. You have to use EntityManager and other related things to use JPA.
You don't need SQL here. SQL always returns list of objects (if you don't use transformers to DTO objects).
Just use HQL (JPQL in JPA)
To get all EmployeeCardOrderLink
getSessionFactory().getCurrentSession()
.createQuery("select link from EmployeeCardOrderLink link").list();
Query "from EmployeeCardOrderLink" will work for Hibernate too (for JPA will not work).

How to make JpaRepository without types, or to make jpa repo with only queries?

I have a couple repositories to work with entities (add,update, delete etc.). And I want to use JpaRepository to fetch statistic data only with #Queries methods, with no update, delete and other CRUD methods. Is there in spring JPA some solution for this case? If I use JpaRepository<PaymentList,Long> I bind to he PaymentList type and get CRUD methods, but to add or delete entities I have distinct repo, and if I use JpaRepository without types I get exception. One of the solutions is to owerride methods from JpaRepository and throw exception while using them, but it looks a bit ugly.
Here is the example of my repository:
#Repository
public interface StatisticRepo extends JpaRepository<PaymentList,Long> {
#Query("SELECT pd.date, SUM(pd.totalPayment) " +
"FROM PaymentDetails pd WHERE pd.date BETWEEN :date_from AND :date_until " +
"GROUP BY pd.date")
List getDailyExpensesStatistic(#Param("date_from") Date dateFrom,
#Param("date_until") Date dateUntil);
}`
The best solution that I found is to use org.springframework.data.repository.Repository. No matter with what type of entity or id. It don't have any methods to store or get data. Maybe someone has better solution...

Kotlin - Inject Android Room SQL language on multiple line queries

How can I get multi-line queries to be injected? It works on Room with Java classes, but does Kotlin support this as well?
E.g. I have 2 queries here, and only the top SQL query (1 line) gets injected.
I tried to follow the steps in this guide but could not find the required settings.
There is an issue at https://youtrack.jetbrains.com/issue/KT-13636 which suggests this is fixed, but I'm not sure how to implement the fix.
You can use a raw string which is more readable anyway:
#Dao
interface ItemDao {
#Query("""
SELECT * FROM Item
WHERE Item.id = :id
""")
fun loadItemById(id: Long): LiveData<Item>
}

Spring data rest - expose default methods

I have a Person Repository as follows
#RepositoryRestResource
public interface PersonRepository extends Repository<Person, String> {
List<Person> findAll();
default List<Person> findNewPersons() {
return findByStartDateAfter(LocalDate.now().minusMonths(3));
}
List<Person> findByStartDateAfter(LocalDate date);
}
I am not able to expose the default method through rest.. is there a way to do it without creating an implementation of the repo ?
I faced a similar problem, and was able to solve it using a SpEL expression inside an HQL query in a #Query annotation.
While nowhere near as clean as using a default method, this was the tidiest way I could find without writing a custom controller or introducing a custom implementation with a new DSL library or something for just this one query.
#Query("select p from Person p where p.startDate > :#{#T(java.time.LocalDate).now().minusMonths(3)}")
List<Person> findNewPersons();
My actual query was different so I might have typoed the syntax here, but the idea is the same and it worked for my case (I was using a LocalDate parameter and finding timestamps on that day by using a findByTimestampBetween style query).