createNativeQuery - return Page - spring-data-jpa

I have the following custom implementation of my repository.
public final EntityManager entityManager;
public ImputacionRepositoryImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public List<ImputacionData> imputacionesList() {
Query q = entityManager.createNativeQuery("SELECT " + "empleado.id as empleadoId,"
+ "MAX(imputacion.dia) as dia," + "imputacion.id as id " + "FROM rrhh.empleado empleado "
+ "JOIN rrhh.imputacion imputacion ON imputacion.empleado = empleado.id "
+ "WHERE empleado.id NOT IN (SELECT empleado.id " + "FROM rrhh.empleado empleado "
+ "LEFT JOIN rrhh.imputacion imputacion ON imputacion.empleado = empleado.id " + "WHERE "
+ "(imputacion.dia >= '2017-06-01' AND imputacion.dia <= '2017-10-31') "
+ "GROUP BY empleado.id,imputacion.empleado, imputacion.id) " + "AND true=true "
+ "GROUP BY empleado.id,imputacion.empleado, imputacion.id ORDER BY imputacion.dia DESC");
List<ImputacionData> imputaciones = q.getResultList();
return imputaciones;
}
And I need that instead of returning a List<ImputacionData>, return Page<ImputacionData>, but I do not know if it is possible, and how to do it.

So you can use page implementation in Spring, in Your case it's may look like:
#Override
public Page<ImputacionData> imputacionesList() {
Query q = entityManager.createNativeQuery("SELECT " + "empleado.id as empleadoId,"
+ "MAX(imputacion.dia) as dia," + "imputacion.id as id " + "FROM rrhh.empleado empleado "
+ "JOIN rrhh.imputacion imputacion ON imputacion.empleado = empleado.id "
+ "WHERE empleado.id NOT IN (SELECT empleado.id " + "FROM rrhh.empleado empleado "
+ "LEFT JOIN rrhh.imputacion imputacion ON imputacion.empleado = empleado.id " + "WHERE "
+ "(imputacion.dia >= '2017-06-01' AND imputacion.dia <= '2017-10-31') "
+ "GROUP BY empleado.id,imputacion.empleado, imputacion.id) " + "AND true=true "
+ "GROUP BY empleado.id,imputacion.empleado, imputacion.id ORDER BY imputacion.dia DESC");
Page<ImputacionData> page = new PageImpl<>(q.getResultList());
return page;
}

Related

How to make native query for nested projection in Spring Data JPA

I need to write a native query for my projection with nested interfaces.
My TransactionView interface:
public interface TransactionView {
Long getId();
TransactionType getType();
LocalDate getDate();
AccountProjection getAcc1();
AccountProjection getAcc2();
interface AccountProjection {
String getName();
CurrencyName getCurrencyCode();
BigDecimal getBalance();
}
BigDecimal getAmount();
PartnerView getPartner();
interface PartnerView {
String getName();
}
String getComment();
CategoryView getCategory();
interface CategoryView {
String getName();
}
}
JpaRepository:
public interface TransactionsRepository extends JpaRepository<Transaction, Long> {
List<TransactionView> findByAcc1PersonIdOrderByDateDesc(int personId);
}
This approach works good and I get JSON like this:
[{
"id":34,
"type":"TRANSFER",
"comment":"test comment",
"date":"2022-12-23",
"amount":200.00,
"acc2":
{
"name":"cash",
"currencyCode":"USD",
"balance":200.00
},
"acc1":
{
"name":"test acc",
"currencyCode":"USD",
"balance":700.00
},
"partner":null,
"category":null
},
{
"id":20,
"type":"EXPENCE",
"comment":"",
"date":"2022-12-13",
"amount":33.07,
"acc2":null,
"acc1":
{
"name":"cash",
"currencyCode":"BYN",
"balance":322.33
},
"partner":
{
"name":"bmw"
},
"category":
{
"name":"auto"
}
}]
But Hibernate generates a very complex query with a lot of extra columns fetching.
My native query returns null nested objects:
#Query(value = "SELECT t.id AS id, " +
"t.transaction_type AS type, " +
"t.transaction_date AS date, " +
"t.amount AS amount, " +
"t.comment AS comment, " +
"a1.balance AS acc1Balance, " +
"a1.currency_code AS acc1CurrencyCode, " +
"a1.name AS acc1Name, " +
"a2.balance AS acc2Balance, " +
"a2.currency_code AS acc2CurrencyCode, " +
"a2.name AS acc2Name, " +
"par.name AS partnerName, " +
"cat.name AS categoryName, " +
"cat.category_type AS categoryType " +
"FROM transaction t " +
"LEFT OUTER JOIN account a1 ON t.acc1_id=a1.id " +
"LEFT OUTER JOIN person per ON a1.person_id=per.id " +
"LEFT OUTER JOIN account a2 ON t.acc2_id=a2.id " +
"LEFT OUTER JOIN partner par ON t.partner_id=par.id " +
"LEFT OUTER JOIN category cat ON t.category_id=cat.id " +
"WHERE per.id=?1 ORDER BY t.transaction_date DESC", nativeQuery = true)
List<TransactionView> findByAcc1PersonIdOrderByDateDescTest(int personId);
[{
"id":34,
"type":"TRANSFER",
"comment":"test comment",
"date":"2022-12-23",
"amount":200.00,
"acc2":null,
"acc1":null,
"partner":null,
"category":null
},
{
"id":20,
"type":"EXPENCE",
"comment":"",
"date":"2022-12-13",
"amount":33.07,
"acc2":null,
"acc1":null,
"partner":null,
"category":null
}]
Also I tried approach from Peter Gyschuk, but it doesn't work.
How can I solve it using native query?

Creating new Objects in JPQL returns only one object

I have a JPA Entity with a large number of fields and millions of records. For a report, I need only some of the fields. So I want to create an Object with the essential fields due to resource constraints. I tried to create a list of new objects in JPQL. It gives only one object as a result, where multiple objects are expected.
String j;
j = "select new lk.gov.health.phsp.pojcs.ClientEncounterComponentBasicDataToQuery("
+ "f.name, "
+ "f.code, "
+ "f.item.code, "
+ "f.shortTextValue, "
+ "f.integerNumberValue, "
+ "f.longNumberValue, "
+ "f.realNumberValue, "
+ "f.booleanValue, "
+ "f.dateValue, "
+ "f.itemValue.code"
+ ") ";
j += " from ClientEncounterComponentItem f "
+ " where f.retired=false "
+ " and f.encounter.id=:eid";
Map m = new HashMap();
m.put("eid", endId);
The EBJ is as follows.
public List<Object> findObjects(String jpql, Map<String, Object> parameters, TemporalType tt) {
TypedQuery<Object> qry = getEntityManager().createQuery(jpql, Object.class);
Set s = parameters.entrySet();
Iterator it = s.iterator();
while (it.hasNext()) {
Map.Entry m = (Map.Entry) it.next();
Object pVal = m.getValue();
String pPara = (String) m.getKey();
if (pVal instanceof Date) {
Date pDate = (Date) pVal;
qry.setParameter(pPara, pDate, TemporalType.DATE);
} else {
qry.setParameter(pPara, pVal);
}
}
try {
return qry.getResultList();
} catch (Exception e) {
return null;
}
}
What am I doing wrong? I am using EclipseLink as the persistence provider.

select join using #NamedNativeQueries on non entity class

I would like to retrieve data from complex join select only for reports propose. I decided to use #NamedNativeQueries in class without #Entity annotation as follows
#NamedNativeQueries({
#NamedNativeQuery(name = "detailInformationForInvoicePurpose",
query = "SELECT DISTINCT b.ShipName, \n" +
" b.ShipAddress, \n" +
" b.ShipCity, \n" +
" b.ShipRegion, \n" +
" b.ShipPostalCode, \n" +
" b.ShipCountry, \n" +
" b.CustomerID, \n" +
" c.CompanyName, \n" +
" c.Address, \n" +
" c.City, \n" +
" c.Region, \n" +
" c.PostalCode, \n" +
" c.Country, \n" +
" concat(d.FirstName, ' ', d.LastName) AS Salesperson, \n" +
" b.OrderID, \n" +
" b.OrderDate, \n" +
" b.RequiredDate, \n" +
" b.ShippedDate, \n" +
" a.CompanyName, \n" +
" e.ProductID, \n" +
" f.ProductName, \n" +
" e.UnitPrice, \n" +
" e.Quantity, \n" +
" e.Discount,\n" +
" e.UnitPrice * e.Quantity * (1 - e.Discount) AS ExtendedPrice,\n" +
" b.Freight\n" +
"FROM Shippers a \n" +
"INNER JOIN Orders b ON a.ShipperID = b.ShipVia \n" +
"INNER JOIN Customers c ON c.CustomerID = b.CustomerID\n" +
"INNER JOIN Employees d ON d.EmployeeID = b.EmployeeID\n" +
"INNER JOIN Order_Details e ON b.OrderID = e.OrderID\n" +
"INNER JOIN Products f ON f.ProductID = e.ProductID\n" +
"ORDER BY b.ShipName",
resultClass = JpaReport.class)
})
public class JpaReport {
private String shipname;
private String shipaddress;
private String shipcity;
private String shipregion;
private String shippostalcode;
private String shipcountry;
private String customerid;
private String companyname;
private String address;
private String city;
private String region;
private String postalcode;
private String country;
private String lastname;
private String firstname;
private Long orderid;
private java.sql.Timestamp orderdate;
private java.sql.Timestamp requireddate;
private java.sql.Timestamp shippeddate;
public JpaReport(String shipname, String shipaddress, String shipcity, String shipregion, String shippostalcode, String shipcountry, String customerid, String companyname, String address, String city, String region, String postalcode, String country, String lastname, String firstname, Long orderid, Timestamp orderdate, Timestamp requireddate, Timestamp shippeddate) {
this.shipname = shipname;
this.shipaddress = shipaddress;
this.shipcity = shipcity;
this.shipregion = shipregion;
this.shippostalcode = shippostalcode;
this.shipcountry = shipcountry;
this.customerid = customerid;
this.companyname = companyname;
this.address = address;
this.city = city;
this.region = region;
this.postalcode = postalcode;
this.country = country;
this.lastname = lastname;
this.firstname = firstname;
this.orderid = orderid;
this.orderdate = orderdate;
this.requireddate = requireddate;
this.shippeddate = shippeddate;
}
When I try to retrieve data as list from JpaReport class I have information please look at screenshot
#Repository
public class JpaReportDaoImpl {
#PersistenceContext
private EntityManager em;
public List<JpaReport> detailInformationForInvoicePurpose(){
List<JpaReport> jpaReport = em.createNamedQuery("detailInformationForInvoicePurpose", JpaReport.class).getResultList();
return jpaReport;
}
}
I have a question:
What am I doing wrong?
This is a good way to retrieve data only for
the report?
I try also to extract data as follows
public List<JpaReport> detailInformationForInvoicePurpose(){
List<JpaReport> jpaReport = em.createNativeQuery("SELECT DISTINCT b.ShipName, \n" +
" b.ShipAddress, \n" +
" b.ShipCity, \n" +
" b.ShipRegion, \n" +
" b.ShipPostalCode, \n" +
" b.ShipCountry, \n" +
" b.CustomerID, \n" +
" c.CompanyName as customersCompasnyName, \n" +
" c.Address, \n" +
" c.City, \n" +
" c.Region, \n" +
" c.PostalCode, \n" +
" c.Country, \n" +
" concat(d.FirstName, ' ', d.LastName) AS Salesperson, \n" +
" b.OrderID, \n" +
" b.OrderDate, \n" +
" b.RequiredDate, \n" +
" b.ShippedDate, \n" +
" a.CompanyName as shipersCompanyName, \n" +
" e.ProductID, \n" +
" f.ProductName, \n" +
" e.UnitPrice, \n" +
" e.Quantity, \n" +
" e.Discount,\n" +
" e.UnitPrice * e.Quantity * (1 - e.Discount) AS ExtendedPrice,\n" +
" b.Freight\n" +
"FROM Shippers a \n" +
"INNER JOIN Orders b ON a.ShipperID = b.ShipVia \n" +
"INNER JOIN Customers c ON c.CustomerID = b.CustomerID\n" +
"INNER JOIN Employees d ON d.EmployeeID = b.EmployeeID\n" +
"INNER JOIN Order_Details e ON b.OrderID = e.OrderID\n" +
"INNER JOIN Products f ON f.ProductID = e.ProductID\n" +
"ORDER BY b.ShipName").getResultList();
return jpaReport;
}
but when I want to iterate by List<JpaReport> as follows I get an error
List<JpaReport> jpaReports = jpaReportDaoImpl.detailInformationForInvoicePurpose();
for (JpaReport jpaReport : jpaReports) {
System.out.println(jpaReport);
}
Caused by: java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to ###################.model.JpaReport
Well as it is not managed entity class, query annotation are not processed at all, resulting in missing query. Move query annotations to a managed (#Entity) class.

AEM CQ5 Query builder Multiple Path with Multiple Properties Issue

Now am facing issue in Querybuilder api while trying with Multiple Path with Multiple Properties.
Code is attached here what I did. It is working fine one path with multiple properties and multiple path with one property. My requirement is like multiple path with multiple properties and also some predicates
suggestion would be appreciated
Map<String, String> map = new HashMap<String, String>();
ArrayList<Predicate> group = new ArrayList<Predicate>();
JSONArray jsonArray = new JSONArray();
if (null != searchPathList && searchPathList.size() > 0) {
mapCount = searchPathList.size();
for (int i = 0; i < searchPathList.size(); i++) {
//map.put("group." + (i + 1) + "_path", searchPathList.get(i));
}
}
// group.add(new Predicate("mypath1").set("path", "/content/opinion/columns"));
// group.add(new Predicate("mypath2").set("path", "/content/opinion/books"));
map.put("group.1_path","/content/opinion/columns");
map.put("group.2_path","/content/opinion/books");
map.put("type", CQJCRConstants.JCRPRIMARYTYPEPAGE);
//combine this group with OR
map.put("group.p.or", "true");
map.put("p.offset", "0");
map.put("p.hits", "full");
if (!TheCommonUtility.isEmpty(searchKeyWord)) {
/* map.put("group." + (mapCount + 1) + "_fulltext", searchKeyWord);
map.put("group." + (mapCount + 1) + "_fulltext.relPath", "jcr:content/#jcr:title");
map.put("group." + (mapCount + 2) + "_fulltext", searchKeyWord);
map.put("group." + (mapCount + 2) + "_fulltext.relPath", "jcr:content/#jcr:description");
map.put("group." + (mapCount + 3) + "_fulltext", searchKeyWord);
map.put("group." + (mapCount + 3) + "_fulltext.relPath", "jcr:content/#cq:tags");
map.put("group." + (mapCount + 4) + "_fulltext", searchKeyWord);
map.put("group." + (mapCount + 4) + "_fulltext.relPath", "jcr:content/#authorName");
map.put("group." + (mapCount + 5) + "_fulltext", searchKeyWord);
map.put("group." + (mapCount + 5) + "_fulltext.relPath", "jcr:content/#SlugName");
PredicateGroup searchpathgroup = new PredicateGroup("path");
searchpathgroup.setAllRequired(false);
searchpathgroup.add(new Predicate("mypath1").set("path", "/content/opinion/columns"));
searchpathgroup.add(new Predicate("mypath2").set("path", "/content/opinion/books"));
*/
PredicateGroup searchKeyWordgroup = new PredicateGroup("property");
searchKeyWordgroup.setAllRequired(false);
Predicate titleskPredicate = new Predicate("title");
titleskPredicate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_LIKE);
titleskPredicate.set("property", "fn:lower-case(#" + "jcr:content/jcr:title");
titleskPredicate.set("value", "%" + searchKeyWord.toLowerCase() + "%");
searchKeyWordgroup.add(titleskPredicate);
Predicate desskPredicate = new Predicate("description");
desskPredicate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_LIKE);
desskPredicate.set("property", "fn:lower-case(#" + "jcr:content/jcr:description");
desskPredicate.set("value", "%" + searchKeyWord.toLowerCase() + "%");
searchKeyWordgroup.add(desskPredicate);
Predicate tagskPredicate = new Predicate("tagssk");
tagskPredicate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_LIKE);
tagskPredicate.set("property", "fn:lower-case(#" + "jcr:content/cq:tags");
tagskPredicate.set("value", "%" + searchKeyWord.toLowerCase() + "%");
searchKeyWordgroup.add(tagskPredicate);
Predicate authorNameskPredicate = new Predicate("authorNameSk");
authorNameskPredicate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_LIKE);
authorNameskPredicate.set("property", "fn:lower-case(#" + JcrConstants.JCR_CONTENT + "/" + "authorName"
+ ")");
authorNameskPredicate.set("value", "%" + searchKeyWord.toLowerCase() + "%");
searchKeyWordgroup.add(authorNameskPredicate);
Predicate slugskPredicate = new Predicate("SlugName");
slugskPredicate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_LIKE);
slugskPredicate.set("property", "fn:lower-case(#" + "jcr:content/SlugName");
slugskPredicate.set("value", "%" + searchKeyWord.toLowerCase() + "%");
searchKeyWordgroup.add(slugskPredicate);
group.add(searchKeyWordgroup);
}
Predicate notPredicate = new Predicate("hideInNav", "property");
notPredicate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_NOT);
notPredicate.set("property", JcrConstants.JCR_CONTENT + "/" + "hideInNav");
notPredicate.set("value", "true");
group.add(notPredicate);
Predicate notMasterTitlePredicate = new Predicate("pageMasterNot", "property");
notMasterTitlePredicate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_UNEQUALS);
notMasterTitlePredicate.set("property", JcrConstants.JCR_CONTENT + "/" + JcrConstants.JCR_TITLE);
notMasterTitlePredicate.set("value", "Master Article");
group.add(notMasterTitlePredicate);
if (!ThecommonUtility.isEmpty(author)) {
Predicate authorNamePredicate = new Predicate("authorName", "property");
authorNamePredicate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_LIKE);
authorNamePredicate
.set("property", "fn:lower-case(#" + JcrConstants.JCR_CONTENT + "/" + "authorName" + ")");
authorNamePredicate.set("value", "%" + author.toLowerCase() + "%");
group.add(authorNamePredicate);
}
if (!ThecommonUtility.isEmpty(tagId)) {
Predicate tagPredecate = new Predicate("tags", "tagid");
tagPredecate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_LIKE);
tagPredecate.set(JcrPropertyPredicateEvaluator.PROPERTY, JcrConstants.JCR_CONTENT + "/" + "cq:tags");
tagPredecate.set("1_" + JcrPropertyPredicateEvaluator.VALUE, tagId);
group.add(tagPredecate);
}
if (!ThecommonUtility.isEmpty(start_time) && !ThecommonUtility.isEmpty(end_time)) {
final Predicate createdDatePredicate = new Predicate("issueDate", "daterange");
createdDatePredicate.set("property", JcrConstants.JCR_CONTENT + "/" + CQJCRConstants.ISSUEDATE);
createdDatePredicate.set("lowerBound", start_time);
createdDatePredicate.set("lowerOperation", ">=");
createdDatePredicate.set("upperBound", end_time);
createdDatePredicate.set("upperOperation", "<=");
group.add(createdDatePredicate);
}
if (!ThecommonUtility.isEmpty(order_by) && order_by.equalsIgnoreCase("cq:lastModified")) {
final Predicate orderByPredicate = new Predicate("orderBy", Predicate.ORDER_BY);
orderByPredicate.set(Predicate.ORDER_BY, "#" + JcrConstants.JCR_CONTENT + "/" + order_by);
orderByPredicate.set("orderby.index", "true");
orderByPredicate.set(Predicate.PARAM_SORT, Predicate.SORT_DESCENDING);
group.add(orderByPredicate);
} else if (!ThecommonUtility.isEmpty(order_by) && order_by.equalsIgnoreCase("oldest")) {
final Predicate orderByPredicate = new Predicate("orderBy", Predicate.ORDER_BY);
orderByPredicate.set(Predicate.ORDER_BY, "#" + JcrConstants.JCR_CONTENT + "/" + order_by);
orderByPredicate.set("orderby.index", "true");
orderByPredicate.set(Predicate.PARAM_SORT, Predicate.SORT_ASCENDING);
group.add(orderByPredicate);
}
try {
session = request.getResourceResolver().adaptTo(Session.class);
Query query = qbuilder.createQuery(PredicateGroup.create(map), session);
for (Predicate p : group) {
query.getPredicates().add(p);
}
query.setExcerpt(true);
query.setStart(startHit);
query.setHitsPerPage(showMoreCount);
result = query.getResult();
Solution : map.put("group.p.or", "true"); put this code in top and use PredicateGroup concept for search path {group=group: or=true[
{3_fulltext=fulltext: relPath=jcr:content/#jcr:title, fulltext=bibi}
{4_fulltext=fulltext: relPath=jcr:content/#jcr:description, fulltext=bibi}
{5_fulltext=fulltext: relPath=jcr:content/#cq:tags, fulltext=bibi}
{6_fulltext=fulltext: relPath=jcr:content/#authorName, fulltext=bibi}
{7_fulltext=fulltext: relPath=jcr:content/#weekSlugName, fulltext=bibi}
]}
{type=type: type=cq:Page}
{path=group: or=true[
{1_mypath1=mypath1: path=/content/week/opinion/columns}
{2_mypath2=mypath2: path=/content/week/opinion/books}
]}
{hideInNav=property: operation=not, value=true, property=jcr:content/hideInNav}
{pageMasterNot=property: operation=unequals, value=Master Article, property=jcr:content/jcr:title}
{authorName=property: operation=like, value=%ajish%, property=fn:lower-case(#jcr:content/authorName)}
{orderBy=orderby: orderby.index=true, sort=desc, orderby=#jcr:content/cq:lastModified}

I am using iOS InAppPurchaseManager

with phonegap 1.5.0rc1 and XCode 4.3.
I can not upgrade my mac for the moment.
When I use plugins I do not have any answer, no alert and no message.
I try to do this :
function onDeviceReady() {
processdiv = document.getElementById('processdiv');
processdiv.innerHTML = "Loading...";
window.plugins.inAppPurchaseManager.onPurchased = function(transactionIdentifier, productId, transactionReceipt) {
console.log('purchased: ' + productId);
/* Give coins, enable subscriptions etc */
}
processdiv.innerHTML += "<br />onPurchased OK";
window.plugins.inAppPurchaseManager.onRestored = function(transactionIdentifier, productId, transactionReceipt) {
console.log('restored: ' + productId);
/* See the developer guide for details of what to do with this */
}
processdiv.innerHTML += "<br />onRestored OK";
window.plugins.inAppPurchaseManager.onFailed = function(errno, errtext) {
console.log('failed: ' + errtext);
}
processdiv.innerHTML += "<br />onFailed OK";
}
function requestProdData(prodStr) {
window.plugins.inAppPurchaseManager.requestProductData(prodStr, function(productId, title, description, price) {
console.log("productId: " + productId + " title: " + title + " description: " + description + " price: " + price);
showAlert("productId: " + productId + " title: " + title + " description: " + description + " price: " + price);
window.plugins.inAppPurchaseManager.makePurchase(productId, 1);
}, function(id) {
console.log("Invalid product id: " + id);
showAlert("par la ?? " + id);
}
);
processdiv.innerHTML = "ProductID: " + prodStr + "<br />";
}
Help
I try to add alert in different place of code to know what is the problem.
I had many products in a test app.
I search example to use this plugins. Thanks.
Do not foget to add plugins inAppPurchaseManager in you plugins Cordova.plist :(