How to use JpaRepository operations (findOne) when having a native query with union all statment - spring

I need to use JpaRepository with a query that has an union statement inside. Is it possible? This is my current implementation and the error I get so far:
Entity:
#Entity
public class PaymentDetails {
#Id
#Column
private String id;
#Enumerated(EnumType.STRING)
#Column(name = "rowtype")
private PaymentType paymentType;
#Embedded
private CardDetails cardDetails;
#Embedded
private BankAccountDetails bankAccountDetails;
Interface and query:
public interface PaymentsRepositoryManagerPayment1 extends JpaRepository<PaymentDetails,String> {
#Query(value = "select id,'CARD' as rowtype, cardnumber, cardtype, nameoncard, expirydate, startdate, securitycode, semafonecr, issuenumber, "
+ "null accountnumber, null accountholdername, null sortcode, null bic, null iban, null currency from pcs.BsbTempCardDetails "
+ "where id = :id union all select id, 'BANK' as rowtype, null cardnumber, null cardtype, null nameoncard, null expirydate, null startdate, "
+ "null securitycode, null semafonecr, null issuenumber, accountnumber, accountholdername, sortcode, bic, iban, currency "
+ "from pcs.BsbTempBankAccountDetails where id = :id", nativeQuery = true) <br>
List< PaymentDetails > findPaymentDetails(#Param("id") String id);
Call:
#Autowired private PaymentsRepositoryManagerPayment1 paymentsRepositoryManagerPayment1;
#Transactional(value = "paymentsRepositoryTransactionManager")
public PaymentDetails retrievePaymentDetailsById1(String id) {
return paymentsRepositoryManagerPayment1.findOne(id);
}
ERROR:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not load an entity: [com.bskyb.repository.payments.model.PaymentDetails#cardId]; SQL [select paymentdet0_.id as id2_0_, paymentdet0_.accountholdername as accounth2_2_0_, paymentdet0_.accountnumber as accountn3_2_0_, paymentdet0_.bic as bic2_0_, paymentdet0_.currency as currency2_0_, paymentdet0_.iban as iban2_0_, paymentdet0_.sortcode as sortcode2_0_, paymentdet0_.cardnumber as cardnumber2_0_, paymentdet0_.cardtype as cardtype2_0_, paymentdet0_.expirydate as expirydate2_0_, paymentdet0_.issuenumber as issuenu11_2_0_, paymentdet0_.nameoncard as nameoncard2_0_, paymentdet0_.securitycode as securit13_2_0_, paymentdet0_.startdate as startdate2_0_, paymentdet0_.rowtype as rowtype2_0_ from PaymentDetails paymentdet0_ where paymentdet0_.id=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not load an entity: [com.bskyb.repository.payments.model.PaymentDetails#cardId]
java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist

All of what you showed doesn't seem to be too related to the exception you see:
The exception complaints about a table not being available. Make sure PaymentDetails exists when you issue the query (this is probably the reason you see the exception).
You call findOne(…). Thus the query declaration on findPaymentDetails(…) doesn't play into the use case at all.

Related

Is there a way to have custom SQL query on top of JPA repository to have BULK UPSERTS?

I have a snowflake database and it doesn't support unique constraint enforcement (https://docs.snowflake.com/en/sql-reference/constraints-overview.html).
I'm planning to have a method on JPA repository with a custom SQL query to check for duplicates before inserting to the table.
Entity
#Entity
#Table(name = "STUDENTS")
public class Students {
#Id
#Column(name = "ID", columnDefinition = "serial")
#GenericGenerator(name = "id_generator", strategy = "increment")
#GeneratedValue(generator = "id_generator")
private Long id;
#Column(name = "NAME")
private String studentName;
}
Snowflake create table query
CREATE table STUDENTS(
id int identity(1,1) primary key,
name VARCHAR NOT NULL,
UNIQUE(name)
);
Repository
public interface StudentRepository extends JpaRepository<Students, Long> {
//
#Query(value = "???", nativeQuery = true)
List<Student> bulkUpsertStudents(List<Student> students);
}
You can use a SELECT query to check for duplicate values in the name column before inserting a new record into the table. For example:
#Query(value = "SELECT * FROM STUDENTS WHERE name = :name", nativeQuery = true)
List<Student> findByName(#Param("name") String name);
This method will return a list of Student records with the specified name value. If the list is empty, it means that there are no records with that name value, and you can safely insert a new record with that name value.
List<Student> studentList = new ArrayList<>();
for (Student student : students) {
List<Student> existingStudents = studentRepository.findByName(student.getName());
if (existingStudents.isEmpty()) {
studentsToInsert.add(student);
}
}
studentRepository.bulkUpsertStudents(studentList)
EDIT
If the above solution doesn't work. You can use the MERGE statement to update existing records in the table if the data has changed. For example, if you want to update the name of a Student if it has changed, you can use the following MERGE statement:
#Query(value = "MERGE INTO students t USING (SELECT :name AS name, :newName AS newName) s
ON t.name = s.name
WHEN MATCHED AND t.name <> s.newName THEN UPDATE SET t.name = s.newName
WHEN NOT MATCHED THEN INSERT (name) VALUES (s.name)", nativeQuery = true)
List<Student> bulkUpsertStudents(List<Student> students);
This query will update the name of each Student in the students list if it has changed, and if a conflict occurs, it will not insert a new record. This will ensure that only unique name values are inserted into the table, without having to perform a separate query for each record.
I was able to overcome this using the below approach but need to verify the performance of the queries.
Repository saveAll() method to save all the entities.
Using the custom nativeQuery as below
INSERT OVERWRITE INTO STUDENTS
WITH CTE AS(SELECT ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY ID) AS RNO, ID, NAME FROM STUDENTS)
SELECT ID, NAME FROM CTE WHERE RNO = 1;
Example code :
import static io.vavr.collection.List.ofAll;
import static io.vavr.control.Option.of;
import static java.util.function.Predicate.not;
public Validation<ValidationError, List<Students>> saveAll(List<String> students) {
return of(students)
.filter(not(List::isEmpty))
.map(this::mapToEntities) // maps the list to list of database entities
.map(repository::saveAll) // save all
.toValidation(ERROR_SAVING_STUDENTS) // vavr validation in case of error
.peek(x -> repository.purgeStudents()) // purging to remove duplicates
.toValidation(ERROR_PURGING_STUDENTS);
}
This issue is only due to snowflake's incapability to check uniqueness.

JPA Projections query with GROUP BY not working with null fields

I would like to replicate a query that runs happily in both MySQL and H2:
SELECT
pedido_linha.produto_id AS material,
COALESCE(pedido_linha.unidade_medida_id, "UN") AS uom,
pedido_linha.data_pedido AS referenceDate,
SUM(COALESCE(pedido_linha.quantidade, 0)) AS totalQuantity,
SUM(COALESCE(pedido_linha.valor_total, 0)) AS totalGross,
SUM(COALESCE(pedido_linha.valor_total, 0) - COALESCE(pedido_linha.valor_descontos, 0) -
COALESCE(pedido_linha.valor_impostos, 0)) AS totalNet,
SUM(COALESCE(pedido_linha.valor_custo, 0)) AS totalCogs
FROM pedido_linha
GROUP BY pedido_linha.produto_id, pedido_linha.data_pedido, COALESCE(pedido_linha.unidade_medida_id, "UN");
As an example the query runs fine in MySQL, even though some Group By fields are empty:
The following attempt has been made extract the grouped results in a JPA closed projection:
public interface AggregatedByMaterialUOMDate {
Produto getMaterial();
UnidadeMedida getUom();
LocalDate getReferenceDate();
Float getTotalQuantity();
Float getTotalGross();
Float getTotalNet();
Float getTotalCogs();
}
Along with the repository query:
#Repository
public interface PedidoLinhaRepository extends JpaRepository<PedidoLinha, PedidoLinha.PedidoLinhaCompositeKey> {
#Query("SELECT pl.produto AS material, "
+ "COALESCE(pl.unidadeMedida, :unidadeMedidaPadrao) AS uom, "
+ "pl.dataPedido AS referenceDate, "
+ "SUM(COALESCE(pl.quantidade, 0)) AS totalQuantity, "
+ "SUM(COALESCE(pl.valorTotal, 0)) AS totalGross, "
+ "SUM(COALESCE(pl.valorTotal, 0) - COALESCE(pl.valorDescontos, 0) - COALESCE(pl.valorImpostos, 0)) AS totalNet, "
+ "SUM(COALESCE(pl.valorCusto, 0)) AS totalCogs "
+ "FROM PedidoLinha pl "
+ "GROUP BY pl.produto, pl.dataPedido, COALESCE(pl.unidadeMedida, :unidadeMedidaPadrao)")
List<AggregatedByMaterialUOMDate> consolidatedSelloutByMaterialUOMDayAtLocation(#Param("unidadeMedidaPadrao") UnidadeMedida unidadeMedidaPadrao);
}
The JPQL query above returns a list with 0 elements, thus inconsistent with the native query previously shown.
We have attempted to change COALESCE(pl.unidadeMedida, :unidadeMedidaPadrao) to simply pl.unidadeMedida (both in the SELECT and GROUP BY clauses), with no success.
The query successfully returned all values only when all references to pl.unidadeMedida were completely removed from both clauses.
Below is a sample of the PedidoLinha (referenced by pl in the query) class showing the reference to UnidadeMedida:
#Getter
#Setter
#NoArgsConstructor
#RequiredArgsConstructor
#EqualsAndHashCode(of = "pedidoLinhaCompositeKey")
#Entity
public class PedidoLinha {
#EmbeddedId
#NonNull // torna campo obrigatório e parâmetro do construtor gerado pelo #Data (lombok)
private PedidoLinhaCompositeKey pedidoLinhaCompositeKey;
#Data // lombok: #ToString, #EqualsAndHashCode, #Getter on all fields #Setter on all non-final fields, and #RequiredArgsConstructor
#NoArgsConstructor
#RequiredArgsConstructor
#Embeddable
#EqualsAndHashCode
public static class PedidoLinhaCompositeKey implements Serializable {
#NonNull // torna campo obrigatório e parâmetro do construtor gerado pelo #Data (lombok)
private String id;
#ManyToOne(optional = false, fetch = FetchType.LAZY)
#NonNull // torna campo obrigatório e parâmetro do construtor gerado pelo #Data (lombok)
private Pedido pedido;
}
#ManyToOne(optional = false)
private Produto produto;
#ManyToOne
private UnidadeMedida unidadeMedida;
public UnidadeMedida getUnidadeMedida() {
return (unidadeMedida == null) ? new UnidadeMedida("UN") : unidadeMedida;
}
// rest of the entity code
}
UnidadeMedida class
#Getter
#Setter
#EqualsAndHashCode(of = "id")
#NoArgsConstructor
#Entity
public class UnidadeMedida {
#Id
private String id;
private String descricao;
public UnidadeMedida(String id) {
this.id = id;
}
}
What could be happening? I believe this could be a Hibernate bug but could not find any reference to this issue.
Turns out the key reason the JPQL query was not turning out any records was the way the implicit joins are made in the database call.
The following code represents the actual SQL code executed in the database (How to show the last queries executed on MySQL?) after running the JPQL query above:
SELECT
pedidolinh0_.produto_id as col_0_0_,
coalesce(pedidolinh0_.unidade_medida_id, 'UN') as col_1_0_,
pedidolinh0_.data_pedido as col_2_0_,
sum(coalesce(pedidolinh0_.quantidade, 0)) as col_3_0_,
sum(coalesce(pedidolinh0_.valor_total, 0)) as col_4_0_,
sum(coalesce(pedidolinh0_.valor_total, 0)-coalesce(pedidolinh0_.valor_descontos, 0)-coalesce(pedidolinh0_.valor_impostos, 0)) as col_5_0_,
sum(coalesce(pedidolinh0_.valor_custo, 0)) as col_6_0_,
produto1_.id as id1_88_, produto1_.ativo as ativo2_88_,
produto1_.data_descontinuacao as data_des3_88_,
produto1_.data_introducao as data_int4_88_,
produto1_.descricao as descrica5_88_,
produto1_.ean as ean6_88_,
produto1_.lote_minimo_requisicoes as lote_min7_88_,
produto1_.multiplo_requisicoes as multiplo8_88_,
produto1_.ncm as ncm9_88_,
produto1_.unidade_medida_padrao_id as unidade10_88_
from pedido_linha pedidolinh0_
inner join produto produto1_ on pedidolinh0_.produto_id=produto1_.id
cross join unidade_medida unidademed2_
cross join pedido pedido3_
where pedidolinh0_.unidade_medida_id=unidademed2_.id
group by
pedidolinh0_.produto_id ,
pedidolinh0_.data_pedido ,
coalesce(pedidolinh0_.unidade_medida_id, 'UN')
The issue is that the translation to SQL automatically includes a a cross join + WHERE clause pedidolinh0_.unidade_medida_id=unidademed2_.id in the query, effectively ignoring every instance where this field is null.
Even though coalescing is applied in the select statement, these records were already ignored by the where clause and thus it has no effect.
The solution was to force a left join in the JPQL query, as shown below:
SELECT
pl.produto AS material,
COALESCE(um, :unidadeMedidaPadrao) AS uom,
pl.dataPedido AS referenceDate,
SUM(COALESCE(pl.quantidade, 0)) AS totalQuantity,
SUM(COALESCE(pl.valorTotal, 0)) AS totalGross,
SUM(COALESCE(pl.valorTotal, 0) - COALESCE(pl.valorDescontos, 0) - COALESCE(pl.valorImpostos, 0)) AS totalNet,
SUM(COALESCE(pl.valorCusto, 0)) AS totalCogs
FROM PedidoLinha pl
LEFT JOIN pl.unidadeMedida um
GROUP BY pl.produto, pl.dataPedido, pl.unidadeMedida
As a result, the cross join statement is replaced by a left outer join in the final SQL executed in the database and is not included in the where clause.
Any insights as to why this design decision (use of cross join + where statement instead of left joins) was made in Hibernate would be appreciated.

Select latest record for each id spring jpa

I have an entity like this:
#Entity
class Point{
#EmbeddedId
private PointIdentity pointIdentity;
private float latitude;
private float longitude;
#Embeddable
public static class PointIdentity implements Serializable {
private Long id;
private ZonedDateTime timestamp;
}
}
There is EmbeddedId, so in "id" column can be multiple records with the same ids.
And I need to get latest record for each id, using CriteriaQuery and JPA specifications I think, but don't know how.
In SQL, this would be something like this:
SELECT id, MAX(timestamp)
FROM geodata
GROUP BY id
Is there any way to do it?
Any help, thanks.
You can easily write a JPQL query:
TypedQuery<Object[]> query = entityManager.createQuery(
"select p.pointIdentity.id, max(p.pointIdentity.timestamp) from Point p group by p.pointIdentity.id",
Object[].class);
List<Object[]> results = query.getResultList();
which translates to:
select
point0_.id as col_0_0_,
max(point0_.timestamp) as col_1_0_
from
point point0_
group by
point0_.id
Alternatively, you can use criteria query:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]> query = criteriaBuilder.createQuery(Object[].class);
Root<Point> point = query.from(Point.class);
query.groupBy(point.get("pointIdentity").get("id"));
query.multiselect(
point.get("pointIdentity").get("id"),
criteriaBuilder.max(point.get("pointIdentity").get("timestamp"))
);
TypedQuery<Object[]> typedQuery = entityManager.createQuery(query);
List<Object[]> results = typedQuery.getResultList();
which produces identical SQL.

Spring Data JPA query to select all value from one join table

I have problem to select all value from one table and few other columns using Spring Data JPA. I am using PostgreSql database and when I send query through PgAdmin I get values I want, but if I use it in Spring Boot Rest returns only one table values (subquery not working). What I am doing wrong?
#Query(value = "SELECT item.*, MIN(myBid.bid) AS myBid, (SELECT MIN(lowestBid.bid) AS lowestbid FROM bids lowestBid WHERE lowestBid.item_id = item.item_id GROUP BY lowestBid.item_id) FROM item JOIN bids myBid ON item.item_id = myBid.item_id WHERE myBid.user_id = :user_id GROUP BY item.item_id", nativeQuery = true)
public List<Item> findAllWithDescriptionQuery(#Param("user_id") UUID userId);
Added Item class
#Data
#Entity(name = "item")
public class Item {
#Id
#GeneratedValue
private UUID itemId;
#NotNull
#Column(name = "title")
#Size(max = 255)
private String title;
#NotNull
#Column(name = "description")
private String description;
#NotNull
#Column(name = "created_user_id")
private UUID createdUserId;
}
The result from your native query cannot simply be mapped to entities due to the in-database aggregation performed to calculate the MIN of own bids, and the MIN of other bids. In particular, your Item entity doesn't carry any attributes to hold myBid or lowestbid.
What you want to return from the query method is therefore a Projection. A projection is a mere interface with getter methods matching exactly the fields returned by your query:
public interface BidSummary {
UUID getItem_id();
String getTitle();
String getDescription();
double getMyBid();
double getLowestbid();
}
Notice how the query method returns the BidSummary projection:
#Query(value = "SELECT item.*, MIN(myBid.bid) AS myBid, (SELECT MIN(lowestBid.bid) AS lowestbid FROM bids lowestBid WHERE lowestBid.item_id = item.item_id GROUP BY lowestBid.item_id) FROM item JOIN bids myBid ON item.item_id = myBid.item_id WHERE myBid.user_id = :user_id GROUP BY item.item_id", nativeQuery = true)
public List<BidSummary> findOwnBids(#Param("user_id") UUID userId);
Return type is List of Item objects and the query specified is having columns which are not part of return object. I recommend using appropriate Entity which full-fills your response type.

Pagination error in SpringBoot "Incorrect syntax near '#P0'" [duplicate]

I'm using Spring Data JPA, and when I use #Query to to define a query WITHOUT Pageable, it works:
public interface UrnMappingRepository extends JpaRepository<UrnMapping, Long> {
#Query(value = "select * from internal_uddi where urn like %?1% or contact like %?1%",
nativeQuery = true)
List<UrnMapping> fullTextSearch(String text);
}
But if I add the second param Pageable, the #Query will NOT work, and Spring will parse the method's name, then throw the exception No property full found. Is this a bug?
public interface UrnMappingRepository extends JpaRepository<UrnMapping, Long> {
#Query(value = "select * from internal_uddi where urn like %?1% or contact like %?1%",
nativeQuery = true)
Page<UrnMapping> fullTextSearch(String text, Pageable pageable);
}
You can use pagination with a native query. It is documented here: Spring Data JPA - Reference Documentation
"You can however use native queries for pagination by specifying the count query yourself:
Example 59. Declare native count queries for pagination at the query method using #Query"
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
A similar question was asked on the Spring forums, where it was pointed out that to apply pagination, a second subquery must be derived. Because the subquery is referring to the same fields, you need to ensure that your query uses aliases for the entities/tables it refers to. This means that where you wrote:
select * from internal_uddi where urn like
You should instead have:
select * from internal_uddi iu where iu.urn like ...
Considering that the UrnMapping class is mapped to the internal_uddi table, I would suggest this:
#Repository
public interface UrnMappingRepository extends JpaRepository<UrnMapping, Long> {
#Query(value = "select iu from UrnMapping iu where iu.urn like %:text% or iu.contact like %:text%")
Page<UrnMapping> fullTextSearch(#Param("text") String text, Pageable pageable);
}
Please note that you might have to turn off native queries with dynamic requests.
With #Query , we can use pagination as well where you need to pass object of Pageable class at end of JPA method
For example:
Pageable pageableRequest = new PageRequest(page, size, Sort.Direction.DESC, rollNo);
Where,
page = index of page (index start from zero)
size = No. of records
Sort.Direction = Sorting as per rollNo
rollNo = Field in User class
UserRepository repo
repo.findByFirstname("John", pageableRequest);
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USER WHERE FIRSTNAME = :firstname)
Page<User> findByLastname(#Param("firstname") String firstname, Pageable pageable);
}
Please reference :Spring Data JPA #Query, if you are using Spring Data JPA version 2.0.4 and later. Sample like below:
#Query(value = "SELECT u FROM User u ORDER BY id")
Page<User> findAllUsersWithPagination(Pageable pageable);
Declare native count queries for pagination at the query method by using #Query
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
Hope this helps
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
Rewrite your query to:
select iu from internal_uddi iu where iu.urn....
description: http://forum.spring.io/forum/spring-projects/data/126415-is-it-possible-to-use-query-and-pageable?p=611398#post611398
I found it works different among different jpa versions, for debug, you'd better add this configurations to show generated sql, it will save your time a lot !
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
for spring boot 2.1.6.RELEASE, it works good!
Sort sort = new Sort(Sort.Direction.DESC, "column_name");
int pageNumber = 3, pageSize = 5;
Pageable pageable = PageRequest.of(pageNumber - 1, pageSize, sort);
#Query(value = "select * from integrity_score_view " +
"where (?1 is null or data_hour >= ?1 ) " +
"and (?2 is null or data_hour <= ?2 ) " +
"and (?3 is null or ?3 = '' or park_no = ?3 ) " +
"group by park_name, data_hour ",
countQuery = "select count(*) from integrity_score_view " +
"where (?1 is null or data_hour >= ?1 ) " +
"and (?2 is null or data_hour <= ?2 ) " +
"and (?3 is null or ?3 = '' or park_no = ?3 ) " +
"group by park_name, data_hour",
nativeQuery = true
)
Page<IntegrityScoreView> queryParkView(Date from, Date to, String parkNo, Pageable pageable);
you DO NOT write order by and limit, it generates the right sql
I had the same issue - without Pageable method works fine.
When added as method parameter - doesn't work.
After playing with DB console and native query support came up to decision that method works like it should. However, only for upper case letters.
Logic of my application was that all names of entity starts from upper case letters.
Playing a little bit with it. And discover that IgnoreCase at method name do the "magic" and here is working solution:
public interface EmployeeRepository
extends PagingAndSortingRepository<Employee, Integer> {
Page<Employee> findAllByNameIgnoreCaseStartsWith(String name, Pageable pageable);
}
Where entity looks like:
#Data
#Entity
#Table(name = "tblEmployees")
public class Employee {
#Id
#Column(name = "empID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotEmpty
#Size(min = 2, max = 20)
#Column(name = "empName", length = 25)
private String name;
#Column(name = "empActive")
private Boolean active;
#ManyToOne
#JoinColumn(name = "emp_dpID")
private Department department;
}
When using nativeQuery that is having (nativeQuery = true), you may do the pagination yourself in the query by adding (LIMIT :sizeValue OFFSET :page)
Note:
Your page value passed to this method should be offset * size
Example
#Query(value = "SELECT * FROM person " +
"LIMIT ?1 OFFSET ?2", nativeQuery = true)
Optional<List<TDriverJob>> findPersons(int size, int page);
I tried all above solution and non worked , finally I removed the Sorting from Pagination and it worked
the following tutorial helped me
-> https://www.baeldung.com/spring-data-jpa-query
At this point 4.3. Spring Data JPA Versions Prior to 2.0.4
VERY IMPORTANT to add \ n-- #pageable \ n
Without this I was wrong
Also the pagination setting must be without ordering
PageRequest paginaConf = new PageRequest ((param1 - 1)
, param2);
Finally to convert the Page <Object []>
Page <Object []> list = myQueryofRepo ();
List <XXXModel> lstReturn = myConversor (list.getContent ());
Page <XXXModel> ret = new PageImpl <XXXModel> (lstReturn, pageConf, param2);
This bugged me for a while but I managed with a very smooth solution.
The challenge is JPA did not automatically detect the count query so I resolved to use the countName which according JPA docs Returns the name of the javax.persistence.NamedQuery to be used to execute count queries when pagination is used. Will default to the named query name configured suffixed by .count.
So I created a named query
#NamedNativeQuery(
name = "[queryName].count",
query = [your count query],
resultSetMapping = "[query resultSetMapping name]"
)
}
As indicated, the count query should be suffixed with .count
Count query returns Long so add the resultSetMapping as
#SqlResultSetMapping(
name="[query resultSetMapping name]",
columns={#ColumnResult(name="count", type = Long.class)})
Then in your repository, use the count query as indicated below
#Query(countName ="[queryName].count" , nativeQuery = true)
Page<Object> [mainQuery](...params)
Hope this helps!

Resources