select join using #NamedNativeQueries on non entity class - jpa

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.

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?

createNativeQuery - return Page

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;
}

azure REST API communication

I'm currently trying retrieve list share available in my Azure account from salesforce. I'm trying to implement the example from below sample code:
https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares#samplerequestandresponse
//private key: access key of my account
string storageKey =private key;
string storageName = 'accountName';
Datetime dt = Datetime.now();
string formattedDate = dt.formatGMT('EEE, dd MMM yyyy HH:mm:ss')+ ' GMT';
system.debug('formattedDate--'+formattedDate);
string CanonicalizedHeaders = 'x-ms-date:'+formattedDate+'\nx-ms-version:2016-05-31';
string CanonicalizedResource = '/' + storageName + '/\ncomp:list';
string StringToSign = 'GET\n\n\n\n\n\n\n\n\n\n\n\n' + CanonicalizedHeaders+'\n'+CanonicalizedResource;
system.debug('StringToSign--'+StringToSign);
Blob temp = EncodingUtil.base64Decode(storageKey);
Blob hmac = Crypto.generateMac('HmacSHA256',Blob.valueOf(StringToSign),temp ); //StringToSign
system.debug('oo-'+EncodingUtil.base64Encode(hmac));
HttpRequest req = new HttpRequest();
req.setMethod('GET');
//req.setHeader('content-type', 'application/xml');
req.setHeader('x-ms-version','2016-05-31' );
req.setHeader('x-ms-date', formattedDate);
string signature = EncodingUtil.base64Encode(hmac);
string authHeader = 'SharedKey salesforcestrongaccount'+':'+signature;
req.setHeader('Authorization',authHeader);
req.setEndpoint('https://<accountName>.file.core.windows.net/?comp=list');
Http http = new Http();
HTTPResponse res;
res = http.send(req);
System.debug(LoggingLevel.INFO, 'http.send result status: ' + res.getStatus());
Any help?
As Gaurav Mantri says, there are something wrong with your stringToSign. So you will get this error.
The right Shared Key Authentication is like this:
StringToSign = VERB + "\n" +
Content-Encoding + "\n" +
Content-Language + "\n" +
Content-Length + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Date + "\n" +
If-Modified-Since + "\n" +
If-Match + "\n" +
If-None-Match + "\n" +
If-Unmodified-Since + "\n" +
Range + "\n" +
CanonicalizedHeaders +
CanonicalizedResource;
Here I create a test demo, you could refer to it.
List share:
string storageAccount = "storage account";
string accessKey = "accountkey";
string resourcePath = "?comp=list";
string uri = #"https://" + storageAccount + ".file.core.windows.net/" + resourcePath;
// Web request
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "GET";
request.Headers["x-ms-date"] = DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture);
request.Headers["x-ms-version"] = "2015-02-21";
String stringToSign = "GET\n"
+ "\n" // content encoding
+ "\n" // content language
+ "\n" // content length
+ "\n" // content md5
+ "\n" // content type
+ "\n" // date
+ "\n" // if modified since
+ "\n" // if match
+ "\n" // if none match
+ "\n" // if unmodified since
+ "\n" // range
+ "x-ms-date:" + request.Headers["x-ms-date"] + "\nx-ms-version:2015-02-21\n" // headers
+ "/" + storageAccount + "/" + "\ncomp:list"; // resources
System.Security.Cryptography.HMACSHA256 hasher = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(accessKey));
string strAuthorization = "SharedKey " + storageAccount + ":" + System.Convert.ToBase64String(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringToSign)));
request.Headers["Authorization"] = strAuthorization;
Task<WebResponse> response = request.GetResponseAsync();
HttpWebResponse responseresult = (HttpWebResponse)response.Result;
using (System.IO.StreamReader r = new System.IO.StreamReader(responseresult.GetResponseStream()))
{
string jsonData = r.ReadToEnd();
Console.WriteLine(jsonData);
}
Result:
Java:
private static final String account = "accountname";
private static final String key = "Key";
public static void main(String args[]) throws Exception {
// String urlString = "http://" + account + ".file.core.windows.net/sampleshare/name.txt";
String urlString = "https://" + account + ".file.core.windows.net/?comp=list";
HttpURLConnection connection = (HttpURLConnection) (new URL(urlString)).openConnection();
getFileRequest(connection, account, key);
connection.connect();
System.out.println("Response message : " + connection.getResponseMessage());
System.out.println("Response code : " + connection.getResponseCode());
BufferedReader br = null;
if (connection.getResponseCode() != 200) {
br = new BufferedReader(new InputStreamReader((connection.getErrorStream())));
} else {
br = new BufferedReader(new InputStreamReader((connection.getInputStream())));
}
System.out.println("Response body : " + br.readLine());
}
public static void getFileRequest(HttpURLConnection request, String account, String key) throws Exception {
SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = fmt.format(Calendar.getInstance().getTime()) + " GMT";
String stringToSign = "GET\n" + "\n" // content encoding
+ "\n" // content language
+ "\n" // content length
+ "\n" // content md5
+ "\n" // content type
+ "\n" // date
+ "\n" // if modified since
+ "\n" // if match
+ "\n" // if none match
+ "\n" // if unmodified since
+ "\n" // range
+ "x-ms-date:" + date + "\nx-ms-version:2015-02-21\n" // headers
+ "/" + account + request.getURL().getPath() + "\ncomp:list"; // resources
System.out.println("stringToSign : " + stringToSign);
String auth = getAuthenticationString(stringToSign);
request.setRequestMethod("GET");
request.setRequestProperty("x-ms-date", date);
request.setRequestProperty("x-ms-version", "2015-02-21");
request.setRequestProperty("Authorization", auth);
}
private static String getAuthenticationString(String stringToSign) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(Base64.decode(key), "HmacSHA256"));
String authKey = new String(Base64.encode(mac.doFinal(stringToSign.getBytes("UTF-8"))));
String auth = "SharedKey " + account + ":" + authKey;
return auth;
}

How to write a dynamic where 'like' query in Entity framework?

Here is my code:
//order my baselist is context.Entity
public static GridData Getdata<T>(ObjectSet<T> baseList,
int currentPage,
int rowsPerPage,
string sortcolumn,
string sortord,
string searchQuery,
string searchColumns)where T: class{
var query = baseList.OrderBy("it." + sortcolumn + " " + sortord);
string strPredicate = string.Empty;
if (!string.IsNullOrEmpty(searchColumns))
{
strPredicate = "it." + searchColumns + " LIKE #" + searchColumns + " ";
query = baseList.Where(strPredicate, new ObjectParameter(searchColumns, searchQuery)).OrderBy("it." + sortcolumn + " " + sortord);
}
}
My problem is i am trying to write down or form a like query in entity framework and seems like it does not support it.
You can use .Contains which is the LIKE operator equivalent in entity framework.
you can use this
query = baseList.Where(baseli=>baseli.Contains(searchColumns )).OrderBy("it." + sortcolumn + " " + sortord);
:)

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 :(