JPA nativeQuery with UNION does not support pagination - spring-boot

Consider the following tables:
TABLE A
id
sys_time
user_id
rent_time
TABLE B
id
sys_time
occur_time
I would like to use a UNION query in MYSQL to have this table and put data from both tables row by row with sys_time order:
TABLE AB
id
sys_time
user_id
occur_time
rent_time
I use the following query:
select id, sys_time, user_id, null as occur_time, rent_time from open_close
union
select id, sys_time, null as user_id, occur_time, null as rent_time from periodic
order by sys_time desc;
Now I define an #Entity with the following structure:
...
#Data
#Entity
#NamedNativeQuery(
name="TotalEntity.getTotal"
, query="select id, sys_time, user_id, null as occur_time, rent_time from open_close\r\n"
+ "union\r\n"
+ "select id, sys_time, null as user_id, occur_time, null as rent_time from periodic \r\n" + "order by sys_time desc;"
, resultClass=TotalEntity.class
)
...
// Entity Fields and so on
and the corresponding Repository:
#Repository
public interface TotalRepository extends JpaRepository<TotalEntity, BigInteger> {
#Query(nativeQuery = true)
public List<TotalEntity> getTotal();
}
Everything is OK up to now.
Now I want to add pagination:
#Repository
public interface TotalRepository extends JpaRepository<TotalEntity, BigInteger> {
#Query(nativeQuery = true)
public Page<TotalEntity> getTotal(Pageable page);
}
and use this:
...
private TotalRepository tr;
...
Pageable pageable = PageRequest.of(page, size,
direction.toUpperCase().equals("ASC") ? Sort.by(sort).ascending() : Sort.by(sort).descending());
Optional<Page<TotalEntity>> pe = Optional.ofNullable(tr.getTotal(pageable));
The following exception is thrown:
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'limit 20' at line 4
It seems that Hibernate can not modify the nativeQuery to add pagination statements. And I know that JPQL and JPA does not supprt UNIONs. Is there any workaround for this?

A workaround would be to introduce a view in the database layer with the union clause, and then execute the query upon the view.
This way, you can hide the union from JPA layer and queries can be executed using pageable as usual.
CREATE VIEW view_name AS
select id, sys_time, user_id, null as occur_time, rent_time from open_close
union
select id, sys_time, null as user_id, occur_time, null as rent_time from periodic
And modify the JpaRepository to query upon the view using prefered way, like native queries, column projections etc.

If you are not planning to use other functionalities from Pageable interface like getting the total records count, number of current slice etc., then try using offset and limit keywords in the query directly for the pagination.
Note : offeset corresponds to page and limit corresponds to size of content in the page

Related

How to query all posts by tag_id in Postgres ManyToMany Relationship in spring JPA repository?

How to query all posts by tag_id in Postgres ManyToMany relationship in Spring JPA repository?
These are the tables:
post
post_tag
tag
id
id_post
id
..
id_tag
..
If I query the PostgreSQL directly via pg_admin Query tool the following sql is working:
SELECT * FROM post WHERE ID IN (
select post_id from post_tag tag WHERE (tag_id = '12'))
I like to have this query in my JPA Repository, but the following isn't working.
#Query(value = "SELECT * FROM post WHERE ID IN (select post_id from
post_tag tag WHERE (tag_id = id))",nativeQuery = true,)
fun findPostsByTagId(id: String): Optional<List<Post>>
How to make this work?
Thanks in advance.
This did the trick:
#Query(value = "SELECT * FROM post WHERE ID IN (select post_id from
post_tag tag WHERE (tag_id = :id))",nativeQuery = true,)
fun findPostsByTagId(id: Long): Optional<List<Post>>
add ":" in front of "id" like sidgate says
changing String to Long for the passed parameter

Entity Graph for nested associations of tables in Spring JPA

There are 3 tables in my db:
SalesOrderMaster
SalesOrderDetail
CustomerMaster
I have repository class SalesOrderDetailRespository.java which has this method findAll()
#EntityGraph(attributePaths = {"SalesOrderMaster"}, type = EntityGraph.EntityGraphType.FETCH)
List<SalesOrderInfo> findAll(#Nullable Specification<SalesOrderInfo> spec);
This is till now fetching the SalesOrderMaster record and associated SalesOrderDetails records. Now my requirement is in SalesOrderInfo class , I have added a new property for showing the Customer Information like Name , country which are there in CustomerMaster table.
The customerMaster table is related to SalesOrderMaster by customerId column. How do I add CustomerMaster table in the existing EntityGraph so that I can get this info?

How to get column name from JPA

My code:
empDet emp = repository.findByActiveFlag("Y");
Here empDet is a entity with 3 columns:
empid
empName
ActiveFlag
Table with 10 rows so i will use foreach
emp.forEach(e-> {
---mycode---
---and here i got values--
});
Now my question is how to get Column name from Jpa or foreach loop
If you have object of Entity class (empDet) in JPA then from that object you can get the all properties of that class.
As you know in JPA class represent table in database and properties represent columns of that table.
if you have an object of empDet e.i emp
empDet emp=repository.findByActiveFlag("Y");
Field[] members = emp.getClass().getDeclaredFields();
for(Field member:members){
System.out.println(member.getName());
}

How to replace SQL Query CONDITION in Spring JPA native query

I have a spring jpa native query(actual query has multiple tables connected) something like below.
#Query(nativeQuery = true, value="
select id, name from TABLE where id NOT IN ('2', '3')")
List<Object> getValueForNOTIN()
#Query(nativeQuery = true, value="
select id, name from TABLE where id IN ('4', '5')")
List<Object> getValueForIN()
Instead of 2 methods, I want to use one method which replaces NOT IN and IN with this 'replaceClause' value.
List<Object> getValueForBoth(#Param("replaceClause)" String replaceClause)
I get error on start of server. Can't I do like this?
You can use a static string like
private String SELECT_NOT_IN_QUERY = "select id, name from TABLE
where id NOT IN ('id1', 'id2')"
private String SELECT_IN_QUERY = "select id, name from TABLE
where id IN ('id1', 'id2')"
then look for id1 and id2 and replace with its values. use the right static string accordingly.

How to use Customize your Queries in JPA with Query Methods (spring boot)

I want to retrieve a specific value from the database based on a criteria without using the query method in Spring JPA.
they query desired is
SELECT TOP 1 * FROM Co2 WHERE Co2.room = ?1 order by co2.id desc
which can be used in a normal native query annotation like so:
public interface Co2Respository extends CrudRepository<Co2, Integer> {
#Query("SELECT TOP 1 * FROM Co2 WHERE Co2.room = ?1 order by co2.id desc",
nativeQuery = true)
Co2 findLastInsertedValueForRoom(int id);
}
the question is how to achieve the same using the custom query method in Spring JPA
I will answer my own question,
the equivalent custom method for the query mentioned above is:
Co2 findTopByRoomOrderByIdDesc(Room room);

Resources